【问题标题】:QML Combobox with QSqlModel带有 QSqlModel 的 QML 组合框
【发布时间】:2019-03-02 15:15:35
【问题描述】:

我目前在用QSqlTableModel 填充QML Combobox 时遇到问题。

示例数据库:

  Table Customer                    Table Project
|   id   |   name   |      |   id   |   name  |  fk_customer  | 
|........|..........|      |........|.........|...............|
|    1   |  name1   |      |    1   |  pro1   |      1        |
|    2   |  name2   |      |    2   |  pro2   |      1        |
|    3   |  name3   |      |    3   |  pro3   |      3        |

我想显示一个带有QML Combobox 的表单以按名称选择客户。
因此,我将组合框模型设置为 QSqlTableModel 和 table="customer" 和 textRole="name"。

我的问题现在在于将Combobox.currentindex 设置为数据库中的正确值,当然还要从组合框中读取selected ID。
Comboboxes 文档指出,每当组合框填充新模型时,其当前索引设置为 1。
我尝试使用来自组合框及其父级的Component.onCompleted 信号设置 currentindex,但所选索引始终设置为1。

所以我想我在实现模型或QML-file.时可能犯了概念错误

有人知道何时以及如何使用 c++ 模型中的给定值预先设置 QML 组合框的建议方法吗?

【问题讨论】:

    标签: qt combobox qml qsqltablemodel qsqlquerymodel


    【解决方案1】:

    由于您没有提供 MCVE,我不明白问题出在哪里,因此我的回复将尝试显示正确的解决方案。

    假设您了解QSqlTableModel 不能直接在QML 中使用,但您必须添加与字段对应的角色并覆盖data() 和roleNames() 方法。

    要获取给定ID的信息,视图的currentIndex必须使用模型的data()方法,因此必须创建相应的QModelIndex和角色,在这种情况下简化该任务我已经实现了一个给定行和字段名称返回数据的函数。

    使用上面我已经实现了以下类:

    sqltablemodel.h

    #ifndef SQLTABLEMODEL_H
    #define SQLTABLEMODEL_H
    
    #include <QSqlTableModel>
    #include <QSqlRecord>
    
    class SqlTableModel : public QSqlTableModel
    {
        Q_OBJECT
        Q_PROPERTY(QStringList fieldNames READ fieldNames)
    public:
        using QSqlTableModel::QSqlTableModel;
        QHash<int, QByteArray> roleNames() const
        {
           QHash<int, QByteArray> roles;
           for (int i = 0; i < record().count(); i ++) {
               roles.insert(Qt::UserRole + i + 1, record().fieldName(i).toUtf8());
           }
           return roles;
       }
        QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
        {
            QVariant value;
            if (index.isValid()) {
                if (role < Qt::UserRole) {
                    value = QSqlQueryModel::data(index, role);
                } else {
                    int columnIdx = role - Qt::UserRole - 1;
                    QModelIndex modelIndex = this->index(index.row(), columnIdx);
                    value = QSqlQueryModel::data(modelIndex, Qt::DisplayRole);
                }
            }
            return value;
        }
        Q_INVOKABLE QVariant data(int row, const QString & fieldName){
            int col = record().indexOf(fieldName);
            if(col != -1 && 0 <= row && row < rowCount()){
                QModelIndex ix = index(row, col);
                return ix.data();
            }
            return QVariant();
        }
        QStringList fieldNames() const{
            QStringList names;
            for (int i = 0; i < record().count(); i ++) {
                names << record().fieldName(i);
            }
            return names;
        }
    };
    
    #endif // SQLTABLEMODEL_H
    

    所以你必须创建模型并将其导出到 QML:

    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
        if(!createConnection()) // open the connection with the DB
            return -1;
    
        SqlTableModel model;
        model.setTable("Customer");
        model.select();
    
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("cppmodel", &model);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    

    并且连接是在 QML 中建立的:

    import QtQuick 2.9
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.4
    
    Window {
        visible: true
        width: 320
        height: 240
        title: qsTr("ComboBox with SqlTableModel")
        ComboBox {
            anchors.centerIn: parent
            model: cppmodel
            textRole: "name"
            Component.onCompleted: currentIndex = 4
            onCurrentIndexChanged: {
                var id = cppmodel.data(currentIndex, "id");
                var name = cppmodel.data(currentIndex, "name");
                console.log(qsTr("currentIndex: %1, id: %2, name: %3").arg(currentIndex).arg(id).arg(name))
            }
        }
    }
    

    完整示例可以在以下link 中找到。

    【讨论】:

    • 感谢您的回复。我想知道我的代码有什么问题:我正在使用 qmlRegisterType 方法将模型导出到 QML,因为我认为在启动时不要对数据库进行所有这些调用可能会更好。但是 model: SqlTableModel { table name: "customer" } 和 Component.onCompleted: { currentIndex = backend.customerIndex } 总是导致 currentIndex = 1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    相关资源
    最近更新 更多