Qt中QStyledItemDelegate的使用(一)
Qt中的代理是用于常见的QTreeView、QListView和QTableView中的一个小工具,它控制视图中每一项的显示方式。当然Qt还提供了QColumnView可供使用,但是我对它不太熟不知道该视图能不能编辑。为了方便开发者自定义项目的显示方式,减少自定义项目带来的需修改的代码量,Qt提供了代理的功能。其中一个名为QStyledItemDelegate的代理可以自定义项目处于编辑状态时的显示方式。比如双击某一项目时用自己的编辑框代替系统默认的编辑框。
QStyledItemDelegate是Qt推荐使用的代理,和它相似的还有QItemDelegate可以用。如果你想修改整个视图的显示方式,请采用自定义视图的方式而不是自定义代理。下面我将给出一个关于QStyledItemDelegate的简单例子给初学者参考。下面的代码测试环境是VS2017和Qt5.9。代码运行效果如下。从图中可看出,复选框代替了编辑状态下系统默认的编辑框:
头文件:
namespace Qt { enum CheckDataRole { ResultRole = Qt::UserRole, /* 自定义的Role,用来放布尔类型的编辑结果 */ }; } class MCheckDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit MCheckDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void setEditorData(QWidget *editor, const QModelIndex &index) const override; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; };
CPP文件:
MCheckDelegate::MCheckDelegate(QObject *parent) : QStyledItemDelegate(parent) { } QWidget *MCheckDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { const QString style = u8R"(QCheckBox { padding-left: 4px; background-color: white; })"; QCheckBox* cbBox = new QCheckBox(u8"启用/禁用", parent); cbBox->setStyleSheet(style); return cbBox; } void MCheckDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QCheckBox* cbWidget = dynamic_cast<QCheckBox*>(editor); cbWidget->setChecked(index.data(Qt::DisplayRole).toString() == u8"启用"); } void MCheckDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { bool state = dynamic_cast<QCheckBox*>(editor)->isChecked(); model->blockSignals(true); model->setData(index, state ? u8"启用" : u8"禁用", Qt::DisplayRole); model->blockSignals(false); model->setData(index, state, Qt::ResultRole); } void MCheckDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { editor->setGeometry(option.rect); }
主窗口构造函数代码如下。本例中QtTest是主窗口类,ui.tvHost是QTableView控件:
QtTest::QtTest(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); ui.tvHost->setItemDelegateForColumn(0, new MCheckDelegate(ui.tvHost)); QStandardItemModel* model = new QStandardItemModel(ui.tvHost); model->setHorizontalHeaderLabels({ u8"状态", u8"说明" }); model->setVerticalHeaderLabels({ u8"设备1", u8"设备2", u8"设备3", u8"设备4" }); model->setColumnCount(2); model->setRowCount(4); for (int i = 0; i < 4; i++) { model->setItem(i, 0, new QStandardItem(u8"启用")); model->setItem(i, 1, new QStandardItem(u8"说明文字")); } ui.tvHost->setModel(model); }