【问题标题】:Find the right qt data model with variable fields找到具有可变字段的正确 qt 数据模型
【发布时间】:2018-07-01 18:30:16
【问题描述】:

我正在寻找数据模型。 Qt 提供了很多选择,所以我想听听您的建议。

这是我的数据模型结构的简化示例:

  • 它有两个字段:字段 1 和字段 2。

  • Field1 可以是“none”、“option”或“number”

  • 如果 field1 为“none”,则 field2 应为空且不包含任何选项。

  • 如果 field1 是“option”,field2 应该给我一个“a”或“b”的选项

  • 如果 field1 是“数字”,field2 应该让我可以选择输入 1 到 100 之间的任何数字。

我想在表单上有一个类似表格的数据视图,带有组合或旋转框来选择数据。应该不能输入指定以外的任何其他数据。

能否请您指出正确的方向,并提供一个示例,说明如何在 Qt 中以最简单的方式实现这一点。

我希望能够将这些数据也存储到一个文件中,我可能会使用 json。

【问题讨论】:

  • 你可以直观地解释你想得到什么,概念上我理解你,但视觉方面不

标签: c++ qt


【解决方案1】:

假设您了解 Qt 的模型/视图系统,并且知道您应该使用 View 来可视化您的数据模型,那么您要进一步实现的是 delegate ,它可以为每个字段提供除文本输入之外的额外界面。

根据这个tutorial,你应该这样做:

继承 QStyledItemDelegate ,创建自己的委托类,例如 MyDelegate


class MyDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    enum  FIELDS
    {

        COL_FIELD1,
    };

    explicit MyDelegate(QObject *parent = nullptr);

    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const Q_DECL_OVERRIDE;

    void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const Q_DECL_OVERRIDE;

    void updateEditorGeometry(QWidget *editor,
        const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;

};

实现这些功能

  • createEditor,定义为用户提供什么样的小部件来执行编辑任务
  • setEditorData,将数据从DataModel转换为widget
  • setModelData,将数据从Widget转换为DataModel
  • updateEditorGeometry,定义在字段中查找的小部件。

在以下代码中,我试图找出您需要提供 field1 的选项。

#include "mydelegate.h"

MyDelegate::MyDelegate(QObject *parent) : QStyledItemDelegate(parent)
{

}


QWidget* MyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QComboBox* __comboBox = new QComboBox(parent);

    if(index.column()==COL_FIELD1)
    {
        __comboBox->addItem("none");
        __comboBox->addItem("option");
        __comboBox->addItem("number");
    }
    else
    {
        //! according to your need...
    }

    return __comboBox;
}

void MyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QComboBox* __comboBox = qobject_cast<QComboBox*>(editor);

    if(index.column()==COL_FIELD1)
    {
         __comboBox->setCurrentText(index.model()->data(index).toString());
    }
}

void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QComboBox* __comboBox = qobject_cast<QComboBox*>(editor);

    model->setData(index,QVariant::fromValue(__comboBox->currentText()));
}

void MyDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

实例化 MyDelegate ,附加到您的视图

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //! prepare a demo model
    QStringListModel *model = new QStringListModel();
       QStringList list;
       list << "a" << "b" << "c";
       model->setStringList(list);

    //! attach a MyDelegate for Row1
    ui->tableView->setModel(model);
    ui->tableView->setItemDelegateForRow(0,new MyDelegate(this));
}

MainWindow::~MainWindow()
{
    delete ui;
}

演示效果如下:

刚刚尝试更改 MyDelegate 的实现内容以获得您需要的效果(例如 spinBox 或 Field2 的不同选项),玩得开心!

【讨论】:

  • 感谢您的回复。我有你的例子工作。我确实将 setItemDelegateForRow 更改为 setItemDelegateForColumn。这样,小部件就可以在所有字段上工作。 QStringListModel 只允许一行字符串。什么是适合二维表的模型?
  • 据我所知,唯一内置的二维表模型是 QtSqlTableModel ,它要求你至少先建立一个简单的 SQL 表。
猜你喜欢
  • 2013-08-19
  • 2014-01-09
  • 1970-01-01
  • 1970-01-01
  • 2023-01-09
  • 2018-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多