C++ Qt 为 QTableView 使用自定义 QItemDelegate
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16660292/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Qt Using Custom QItemDelegate for QTableView
提问by arnm
I followed the Spin Box Delegate tutorial, which Qt provides, to try to implement my own QItemDelegate
. It would be used to specify a QComboBox
to represent data in a QTableView
cell but it is not working.
我按照 Qt 提供的 Spin Box Delegate 教程尝试实现我自己的QItemDelegate
. 它将用于指定 aQComboBox
来表示QTableView
单元格中的数据,但它不起作用。
My biggest problem is that I don't know when my QItemDelegate
is going to be utilized.
我最大的问题是我不知道我什么时候QItemDelegate
会被利用。
when
itemModel->setData()
is used or whenitemModel->setItem()
. I would suspectsetItem()
because I reimplemented aQItemDelegate
(emphasis on the "Item") but the tutorial usessetData()
and it works fine.I know that if the specified
QItemDelegate
does not work it uses the default one but how do I now that the one I specified did not work?when should I suspect for
QTableView
to use my delegate. I would like to specify which delegates to use for each cell. Is this possible or does theQTableView
only use one delegate throughout?How would I specify the items to populate the
QComboBox
once it gets displayed by theQTableView
?
何时
itemModel->setData()
使用或何时使用itemModel->setItem()
。我会怀疑setItem()
是因为我重新实现了一个QItemDelegate
(强调“项目”),但本教程使用setData()
并且工作正常。我知道如果指定的
QItemDelegate
不起作用,它会使用默认的,但是现在我指定的不起作用怎么办?我什么时候应该怀疑
QTableView
使用我的委托。我想指定每个单元格使用哪些委托。这是可能的还是QTableView
整个过程中唯一使用一个代表?QComboBox
一旦它被 显示,我将如何指定要填充的项目QTableView
?
I implemented QItemDelegate
here:
我QItemDelegate
在这里实施:
- the part where I try to add the cell which is suppose to use the
QComboBox
is under the comment "Enabled" in mainwindow.cpp further down this post.
- 我尝试添加假设使用的单元格的部分
QComboBox
在 mainwindow.cpp 中的注释“已启用”下,在这篇文章的下方。
qcomboboxitemdelegate.h
qcomboboxitemdelegate.h
#ifndef QCOMBOBOXITEMDELEGATE_H
#define QCOMBOBOXITEMDELEGATE_H
#include <QItemDelegate>
#include <QComboBox>
class QComboBoxItemDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit QComboBoxItemDelegate(QObject *parent = 0);
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index);
void setEditorData(QWidget *editor, const QModelIndex &index);
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index);
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index);
signals:
private:
};
#endif // QCOMBOBOXITEMDELEGATE_H
qcomboboxitemdelegate.cpp
qcomboboxitemdelegate.cpp
#include "qcomboboxitemdelegate.h"
#include <QDebug>
QComboBoxItemDelegate::QComboBoxItemDelegate(QObject *parent)
: QItemDelegate(parent)
{
}
QWidget* QComboBoxItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) {
// create widget for use
QComboBox* comboBox = new QComboBox(parent);
return comboBox;
}
void QComboBoxItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) {
// update model widget
QString value = index.model()->data(index, Qt::EditRole).toString();
qDebug() << "Value:" << value;
QComboBox* comboBox = static_cast<QComboBox*>(editor);
comboBox->setCurrentIndex(comboBox->findText(value));
}
void QComboBoxItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) {
// store edited model data to model
QComboBox* comboBox = static_cast<QComboBox*>(editor);
QString value = comboBox->currentText();
model->setData(index, value, Qt::EditRole);
}
void QComboBoxItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) {
editor->setGeometry(option.rect);
}
mainwindow.cpp : this is where I initialize the QStandardItemModel
mainwindow.cpp :这是我初始化 QStandardItemModel
void MainWindow::init() {
itemModel = new QStandardItemModel(this);
}
void MainWindow::setupUi() {
this->setWindowTitle("QAlarmClock");
QStringList labelList;
labelList << "Alarm Name" << "Time" << "Enabled";
itemModel->setHorizontalHeaderLabels(labelList);
ui->tableView->setModel(itemModel);
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableView->setItemDelegate(comboBoxItemDelegate);
}
void MainWindow::on_actionNew_triggered() {
alarmDialog = new AlarmDialog(this);
connect(alarmDialog, SIGNAL(on_close()), this, SLOT(on_alarmDialog_close()));
alarmDialog->exec();
}
mainwindow.cpp : this is where I update QStandardItemModel
mainwindow.cpp :这是我更新的地方 QStandardItemModel
void MainWindow::on_alarmDialog_close() {
QString alarmName = alarmDialog->getAlarmName();
QDateTime alarmDateTime = alarmDialog->getDateTime();
itemModel->insertRow(itemModel->rowCount());
int rowCount = itemModel->rowCount();
// Alarm Name
QStandardItem* alarmItem = new QStandardItem(QIcon("res/alarmclock.ico"), alarmName);
itemModel->setItem(rowCount - 1 , 0, alarmItem);
// Date Time
QStandardItem* dateTimeItem = new QStandardItem();
dateTimeItem->setText(alarmDateTime.toString());
dateTimeItem->setEditable(false);
itemModel->setItem(rowCount - 1, 1, dateTimeItem);
// Enabled
QStandardItem* enabledItem = new QStandardItem();
QList<QStandardItem*> optionList;
optionList << new QStandardItem("Enabled") << new QStandardItem("Disabled");
enabledItem->appendRows(optionList);
itemModel->setItem(rowCount - 1, 2, enabledItem);
}
Edit 1
编辑 1
qcomboboxdelegate.cpp
qcomboboxdelegate.cpp
QWidget* QComboBoxItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) {
// create widget for use
qDebug() << "Column: " << index.column();
if (index.column() == 2) {
QComboBox* comboBox = new QComboBox(parent);
QStringList values;
values << "Enabled" << "Disabled";
comboBox->addItems(values);
return comboBox;
} else {
return QItemDelegate::createEditor(parent, option, index);
}
}
mainwindow.cpp
主窗口.cpp
void MainWindow::on_alarmDialog_close() {
QList<QStandardItem*> row;
QString alarmName = alarmDialog->getAlarmName();
QDateTime alarmDateTime = alarmDialog->getDateTime();
QString status = "Enabled";
// Alarm Name
QStandardItem* alarmItem = new QStandardItem(QIcon("res/alarmclock.ico"), alarmName);
row << alarmItem;
// Date Time
QStandardItem* dateTimeItem = new QStandardItem();
dateTimeItem->setText(alarmDateTime.toString());
dateTimeItem->setEditable(false);
row << dateTimeItem;
// Enabled
QStandardItem* statusItem = new QStandardItem(status);
row << statusItem;
itemModel->appendRow(row);
}
采纳答案by hank
First, you should have a description of your model columns:
首先,您应该对模型列进行描述:
enum Columns
{
COL_NAME,
COL_TIME,
COL_STATUS
}
Your delegate should only work for the last column.
您的委托应该只适用于最后一列。
Here is an example of how you can populate your model:
以下是如何填充模型的示例:
for (int i = 0; i < 5; ++i)
{
QStandardItem *itemName = new QStandardItem(QString("name %1").arg(i));
QStandardItem *itemTime = new QStandardItem(QString("time %1").arg(i));
QString status;
if (i % 2 == 0)
{
status = "Enabled";
}
else
{
status = "Disabled";
}
QStandardItem *itemStatus = new QStandardItem(status);
QList<QStandardItem*> row;
row << itemName << itemTime << itemStatus;
model->appendRow(row);
}
As I said, your delegate should only work for the last column. So all methods you have reimplemented should have a column check like this:
正如我所说,您的委托应该只适用于最后一列。所以你重新实现的所有方法都应该有一个这样的列检查:
QWidget* QComboBoxItemDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index)
{
if (index.column() == COL_STATUS)
{
QStringList values;
values << "Enabled" << "Disabled";
QComboBox* comboBox = new QComboBox(parent);
comboBox->addItems(values);
return comboBox;
}
else
{
return QItemDelegate::createEditor(parent, option, index);
}
}
You should add this check to the other methods: if the current column is not the status column, the base class (QItemDelegate
) implementation should be used.
您应该将此检查添加到其他方法:如果当前列不是状态列,QItemDelegate
则应使用基类 ( ) 实现。
Then you set your delegate to your view:
然后您将委托设置为您的视图:
ui->tableView->setItemDelegate(new ComboBoxDelegate);
If you do everything right, a combo Box will appear in the last column if you try to edit its values.
如果一切顺利,当您尝试编辑其值时,最后一列将出现一个组合框。
回答by arnm
So I figured out that I did not override the correct function prototypes..! I forgot that they had const in the prototype meaning that I was not overriding any functions so it was using the default ones. Here are the correct virtual functions that have to be re-implemented: http://qt-project.org/doc/qt-5.0/qtwidgets/qitemdelegate.html
所以我发现我没有覆盖正确的函数原型..!我忘了他们在原型中有 const 意味着我没有覆盖任何函数,所以它使用的是默认函数。以下是必须重新实现的正确虚拟功能:http: //qt-project.org/doc/qt-5.0/qtwidgets/qitemdelegate.html
回答by CodeLurker
Even more simply; I found QTableView::setItemDelegateForColumn() to work admirably for a column. For example, in your MainWindow, you could make a member:
更简单;我发现 QTableView::setItemDelegateForColumn() 非常适合用于列。例如,在您的 MainWindow 中,您可以创建一个成员:
QComboBoxItemDelegate dgtComboDelegate;
Then, in your ctor, or init(), you could have
然后,在您的 ctor 或 init() 中,您可以拥有
ui->tableView->setItemDelegateForColumn(2, dgtComboDelegate);
If you wanted that to happen for a single cell, that's when you need to test on the index.column() and index.row().
如果您希望单个单元格发生这种情况,那么您需要在 index.column() 和 index.row() 上进行测试。
You know, you don't have to create a QTableView to do this either. E.g., see the ?:
您知道,您也不必创建 QTableView 来执行此操作。例如,看到?:
Qt - Centering a checkbox in a QTable
The OP doesn't give the declaration for a table widget or view; but it does have the QTableView tag. It should work equally well for either.
OP 没有给出表格小部件或视图的声明;但它确实有 QTableView 标签。它应该同样适用于任何一个。
In the latter case, you can do ui->tableWidget->setItemDelegateForColumn(2, dgtComboDelegate);
and never have to make your own model. Just use setData() on the items you create (or even later, for that matter,) to initialize their values.
在后一种情况下,您可以ui->tableWidget->setItemDelegateForColumn(2, dgtComboDelegate);
并且永远不必制作自己的模型。只需在您创建的项目上使用 setData()(或者甚至稍后,就此而言)来初始化它们的值。