QML Combobox с QSqlModel - PullRequest
       30

QML Combobox с QSqlModel

0 голосов
/ 26 сентября 2018

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

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

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

1 Ответ

0 голосов
/ 26 сентября 2018

Я не понимаю, в чем проблема, поскольку вы не предоставляете 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))
        }
    }
}

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

...