如何使用模型与QML? [英] How to Use Models with QML?

查看:142
本文介绍了如何使用模型与QML?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用qml和c ++编写的GUI。
有2个组合框(qt control 5.1)。第二个组合框必须在运行时更新第一个的值时更改。

I have a GUI written in qml and c++. There are 2 comboboxes (qt control 5.1). Second combobox has to update at runtime whenever the value of the first one is changed.

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

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

这是我从c ++给qml的2个模型。

These are 2 models that I give to qml from 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);

        }

这是第一个组合框。如你所见,第二个组合框的c ++模型每次更改第一个组合框的值时更新(mainwin.unitGenerator(typebox.currentText))。但它似乎没有更新组合框的模型。

This is the first combobox. As you see, the c++ model of second combobox is updated every time the value of the first is changed (mainwin.unitGenerator(typebox.currentText)). But it does not seem to update the combobox's model.

如何在运行时更新qml的模型?

How can I update qml's model on runtime?

推荐答案

甚至开始解决你的问题,我们需要看看 unitGenerator 方法。如果您使用自定义模型,则几乎可以肯定您未正确实施通知。我现在的赌注是,你不是信号的模型重置。

To even begin to address your issue, we'd need to see what the unitGenerator method does. If you're using a custom model, it's almost certain that you're not correctly implementing the notifications. My bet at the moment would be that you're not signaling the model reset.

下面是一个完整的代码示例,显示如何绑定 QStringListModel 添加到可编辑的 ListView ComboBox 第二个 ComboBox 的模型基于从第一个的选择重新生成。

Below is a complete code example that shows how you can tie a QStringListModel to an editable ListView and to ComboBoxes. The second ComboBox's model is regenerated based on the selection from the first one. This presumably approximates your desired functionality.

注意由 QStringListModel 执行的角色的具体处理。模型将显示和编辑角色几乎相同:它们都被映射到列表中的字符串值。但是,当您更新特定角色的数据时, dataChanged 信号仅承载您已更改的角色。这可以用于打破可能以其他方式存在于模型编辑器项(TextInput)中的绑定循环。当您使用自定义模型时,您可能需要实现类似的功能。

Note the specific handling of roles done by the QStringListModel. The model treats the display and edit roles almost the same: they both are mapped to the string value in the list. Yet when you update a particular role's data, the dataChanged signal carries only the role that you've changed. This can be used to break a binding loop that might be otherwise present in the model editor item (TextInput). When you use a custom model, you may need to implement similar functionality.

display 角色用于绑定组合框到模型。 edit 角色用于预填充编辑器对象。编辑器的 onTextChanged 信号处理程序正在更新 display 角色,这不会导致绑定循环本身。如果处理程序正在更新 edit 角色,它将通过 text 属性引起绑定循环。

The display role is used to bind the combo boxes to the model. The edit role is used to pre-populate the editor objects. The editor's onTextChanged signal handler is updating the display role, and this doesn't cause a binding loop to itself. If the handler was updating the edit role, it would cause a binding loop via the text property.

在QML中有各种各样的模型。在内部,QML将包装一个模型中几乎任何东西。任何内部不是QObject 但仍然可以是一个模型(例如 QVariant ),不会通知任何人任何东西。

There are various kinds of "models" in QML. Internally, QML will wrap almost "anything" in a model. Anything that is internally not a QObject yet can still be a model (say a QVariant), won't be notifying anyone about anything.

例如,基于 QVariant 的一个模型,它包装一个 int 不会发出通知,因为 QVariant 不是可以发出变化的 QObject

For example, a "model" based on QVariant that wraps an int will not issue notifications, because QVariant is not a QObject that could signal changes.

同样,如果你的model与从 QObject 派生的类的属性值绑定, code> emit 属性更改通知信号,它也不会工作。

Similarly, if your "model" is tied to a property value of a class derived from QObject, but you fail to emit the property change notification signal, it also won't work.

不知道你的模型类型,不可能告诉。

Without knowing what your model types are, it's impossible to tell.

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"

这篇关于如何使用模型与QML?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆