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);
}

 

posted @ 2023-11-13 16:02  兜尼完  阅读(2394)  评论(0编辑  收藏  举报