2

我目前面临QML ComboboxQSqlTableModel.

示例数据库:

  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按名称选择客户。
因此,我将组合框模型设置为QSqlTableModelwithtable="customer"textRole="name"

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

所以我想我在实现模型或QML-file.

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

4

1 回答 1

2

我不明白问题是什么,因为您没有提供 MCVE,所以我的回复将尝试显示正确的解决方案。

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

要获取给定视图的信息,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))
        }
    }
}

完整的示例可以在以下链接中找到。

于 2018-09-26T20:20:14.147 回答