Jak używać modeli z QML?

Mam GUI napisane w qml i c++. Istnieją 2 comboboxy (Kontrola qt 5.1). Drugi combobox musi aktualizować się w czasie wykonywania przy każdej zmianie wartości pierwszego.

maincontext->setContextProperty("typemodel", QVariant::fromValue(m_typemodel));

maincontext->setContextProperty("unitmodel", QVariant::fromValue(m_unitmodel));

Są to 2 modele, które daję qml z c++.

ComboBox {
    id: typebox

    anchors.left: text1.right
    anchors.leftMargin: 5
    signal changed(string newtext)

    width: 70
    height: 23
    anchors.top: parent.top
    anchors.topMargin: 37
    model: typemodel

    onCurrentTextChanged: {

        mainwin.unitGenerator(typebox.currentText);

    }
To pierwszy combobox. Jak widać, model C++ drugiego comboboxu jest aktualizowany za każdym razem, gdy zmienia się wartość pierwszego (mainwin.unitGenerator (typebox.currentText)). Ale wydaje się, że nie aktualizuje modelu combobox.

Jak zaktualizować model qml w trybie runtime?

Author: eyllanesc, 2013-09-04

2 answers

Aby nawet zacząć rozwiązywać twój problem, musimy zobaczyć, co robi metoda unitGenerator. Jeśli używasz modelu niestandardowego, jest prawie pewne, że nie wdrażasz powiadomień poprawnie. Założę się, że nie sygnalizujesz resetu modelu.

Poniżej znajduje się kompletny przykład kodu, który pokazuje, jak można powiązać QStringListModel z edytowalnym ListViewi ComboBox es. Drugi model ComboBox jest regenerowany na podstawie wyboru z pierwszego. To prawdopodobnie przybliża pożądaną funkcjonalność.

Zwróć uwagę na specyficzną obsługę ról wykonywaną przez QStringListModel. Model traktuje role wyświetlania i edycji prawie tak samo: obie są mapowane do wartości łańcuchowej na liście. Jednak kiedy aktualizujesz dane konkretnej roli, sygnał dataChanged niesie tylko rolę, którą zmieniłeś. Można to wykorzystać do przerwania pętli wiążącej, która w innym przypadku może być obecna w elemencie edytora modeli (TextInput). W przypadku korzystania z modelu niestandardowego może być konieczne zaimplementuj podobną funkcjonalność.

Rola display jest używana do łączenia pól combo z modelem. Rola edit służy do wstępnego wypełniania obiektów edytora. Funkcja obsługi sygnału onTextChanged edytora aktualizuje rolę display, a to nie powoduje pętli wiążącej do siebie. Jeśli funkcja obsługi aktualizowała rolę edit, wywołałaby pętlę wiążącą za pośrednictwem właściwości text.

Na modelach w QML

Istnieją różne rodzaje "modeli" w QML. Wewnętrznie, QML zawija prawie "wszystko" w modelu. Wszystko, co jest wewnętrznie , a nie QObject , nadal może być modelem (powiedzmy QVariant), nie będzie powiadamiać nikogo o niczym.

Na przykład "model" oparty na QVariant, który owija int nie będzie wysyłać powiadomień, ponieważ QVariant nie jest QObject, które mogłyby sygnalizować zmiany.

Podobnie, jeśli twój "model" jest powiązany z wartością właściwości klasy pochodzącej z QObject, ale nie uda Ci się emit sygnału powiadomienia o zmianie właściwości, to również to nie zadziała.

Bez wiedzy, jakie są Twoje typy modelek, nie da się powiedzieć.

Main.qml

import QtQuick 2.0
import QtQuick.Controls 1.0

ApplicationWindow {
    width: 300; height: 300
    ListView {
        id: view
        width: parent.width
        anchors.top: parent.top
        anchors.bottom: column.top
        model: model1
        spacing: 2
        delegate: Component {
            Rectangle {
                width: view.width
                implicitHeight: edit.implicitHeight + 10
                color: "transparent"
                border.color: "red"
                border.width: 2
                radius: 5
                TextInput {
                    id: edit
                    anchors.margins: 1.5 * parent.border.width
                    anchors.fill: parent
                    text: edit // "edit" role of the model, to break the binding loop
                    onTextChanged: model.display = text
                }
            }
        }
    }
    Column {
        id: column;
        anchors.bottom: parent.bottom
        Text { text: "Type";  }
        ComboBox {
            id: box1
            model: model1
            textRole: "display"
            onCurrentTextChanged: generator.generate(currentText)
        }
        Text { text: "Unit"; }
        ComboBox {
            id: box2
            model: model2
            textRole: "display"
        }
    }
}

Main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QStringListModel>
#include <QQmlContext>

class Generator : public QObject
{
    Q_OBJECT
    QStringListModel * m_model;
public:
    Generator(QStringListModel * model) : m_model(model) {}
    Q_INVOKABLE void generate(const QVariant & val) {
        QStringList list;
        for (int i = 1; i <= 3; ++i) {
            list << QString("%1:%2").arg(val.toString()).arg(i);
        }
        m_model->setStringList(list);
    }
};

int main(int argc, char *argv[])
{
    QStringListModel model1, model2;
    Generator generator(&model2);
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    QStringList list;
    list << "one" << "two" << "three" << "four";
    model1.setStringList(list);

    engine.rootContext()->setContextProperty("model1", &model1);
    engine.rootContext()->setContextProperty("model2", &model2);
    engine.rootContext()->setContextProperty("generator", &generator);

    engine.load(QUrl("qrc:/main.qml"));
    QObject *topLevel = engine.rootObjects().value(0);
    QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
    window->show();
    return app.exec();
}

#include "main.moc"
 31
Author: Kuba Ober,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-23 18:04:12

To właściwie odpowiedź / komentarz do odpowiedzi @KubaOber.

Stwierdziłem, że w rzeczywistości nie jest konieczne wykonywanie specjalnych trików przy użyciu wielu ról, jeśli wiąże się z odpowiednim zdarzeniem:

onAccepted: model.edit = text

Działa bez zarzutu i nie tworzy żadnej pętli update (ponieważ jest wywoływana tylko przy modyfikacjach"human" /input).

 3
Author: Simon Schmeißer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-30 17:04:48