Qt中QItemEditorFactory的使用

发布时间 2024-01-10 11:00:20作者: 兜尼完

一般而言QItemEditorFactory是用于替换Qt中已有的数据类型的编辑器控件。因为如果是自定义类型的话,用它也比较复杂,还不如直接自定义一个新的QStyledItemDelegate。尽管如此,本文也给出一个自定义数据类型的例子,用于解释QItemEditorFactory的用法。本例子开发环境是VS2017和Qt5.9。下图是代码运行截图:

Misc.h文件。下方的MDiyType就是我们的自定义类型。MDiyBox是单元格处于编辑状态时用于编辑MDiyType的编辑框。MDiyDelegate是我们的委托,它只实现了displayText(...)函数用于将自定义类型转换成字符串用于在非编辑状态下显示数据:

struct MDiyType
{
    int value;
};

Q_DECLARE_METATYPE(MDiyType);

class MDiyBox : public QSpinBox
{
    Q_OBJECT
    Q_PROPERTY(MDiyType value READ value WRITE setValue)

public:
    MDiyBox(QWidget* parent = 0);
    MDiyType value() const;
    void setValue(const MDiyType& v);
};

class MDiyDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    MDiyDelegate(QObject *parent = 0);
    QString displayText(const QVariant &value, const QLocale &locale) const override;
};

Misc.cpp文件:

MDiyBox::MDiyBox(QWidget* parent) : 
    QSpinBox(parent)
{
    setRange(0, 1000);
    setStyleSheet(u8R"(MDiyBox { border: 1px solid rgb(255, 12, 12); })");
}

MDiyType MDiyBox::value() const
{
    return MDiyType{ QSpinBox::value() };
}

void MDiyBox::setValue(const MDiyType& v)
{
    QSpinBox::setValue(v.value);
}

/////////////////////////////////////////////////////////////////////////////////////////

MDiyDelegate::MDiyDelegate(QObject *parent) :
    QStyledItemDelegate(parent)
{
}

/* 此函数用于将自定义类型转换成字符串 */
/* 否则的话QTableView不知道如何显示自定义类型MDiyType */
QString MDiyDelegate::displayText(const QVariant &value, const QLocale &locale) const
{
    MDiyType data = value.value<MDiyType>();
    return QString::number(data.value);
}

主窗口的构造函数如下。下面的代码中QtTest是主窗口类,ui.tvHost是QTableView控件。变量spinFact要在程序结束时自己手动释放,因为它不是QObject的子类,无法实现自动释放:

QtTest::QtTest(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    int diyTypeId = qRegisterMetaType<MDiyType>("MDiyType");
    MDiyDelegate* spinDel = new MDiyDelegate(ui.tvHost);
    QItemEditorFactory* spinFact = new QItemEditorFactory; /* 这个指针要自己释放 */
    QItemEditorCreatorBase* spinBase = new QItemEditorCreator<MDiyBox>("value");
    spinFact->registerEditor(diyTypeId, spinBase);
    spinDel->setItemEditorFactory(spinFact);
    ui.tvHost->setItemDelegateForColumn(0, spinDel);

    QStandardItemModel* model = new QStandardItemModel(ui.tvHost);
    QStandardItem* item0 = new QStandardItem;
    item0->setData(QVariant::fromValue(MDiyType{ 123 }), Qt::DisplayRole);
    model->setItem(0, item0);
    QStandardItem* item1 = new QStandardItem;
    item1->setData(QVariant::fromValue(MDiyType{ 456 }), Qt::DisplayRole);
    model->setItem(1, item1);
    QStandardItem* item2 = new QStandardItem;
    item2->setData(QVariant::fromValue(MDiyType{ 789 }), Qt::DisplayRole);
    model->setItem(2, item2);
    QStandardItem* item3 = new QStandardItem;
    item3->setData(QVariant::fromValue(MDiyType{ 101 }), Qt::DisplayRole);
    model->setItem(3, item3);
    ui.tvHost->setModel(model);
}