QML Combobox с QSqlModel

Я в настоящее время сталкиваюсь с проблемами с заполнением QML Combobox с QSqlTableModel,

Пример базы данных:

  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 Сигнал из выпадающего списка и его родителя, но выбранный индекс всегда был установлен на 1,

Так что я думаю, что, возможно, сделал концептуальную ошибку при реализации модели или QML-file.

Кто-нибудь знает предложенный способ, когда и как предварительно установить Combobox QML с заданным значением из модели C++?

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

Полный пример можно найти по следующей ссылке.

Другие вопросы по тегам