c++ - QML 绑定(bind)整数属性 - C++ 中的更改未发送到 QML

标签 c++ qml qt5 qtquick2 qtquickcontrols

我是 QtQuick 控件的新手,我想创建一个简单的 GUI,但在将某些 C++ 变量绑定(bind)到 qml 小部件属性时遇到了以下问题: 在下面的简化示例中,我有一个组合框,我想为其分配一个项目列表,并且还能够设置从应用程序的 C++ 端选择哪个项目。

对于 test_list/model 对,一切都完全按照我的预期工作,但对于 test_index/currentIndex 则不然。在将 test_index 设置为 2 并调用通知后,什么也没有发生——我希望应该调用 READ 方法 (getIndex),但它不是(尽管它是针对 test_list 的)。从 GUI 更改索引有效,即由于 onCurrentIndexChanged,值从 qml 发送到 c++ 端,但反之则不起作用。所以在调用 modifyValues() 之后,组合框中有四个项目 - 0、1、2、3 - 但 currentIndex 仍然是 0,因此选择了“0”项目(同时,test_index 等于 2)。

奇怪的是 getIndex 确实在第一次创建小部件时被调用。我读过更改 qml 中的属性将终止所有声明性绑定(bind),但我不明白为什么会在这里发生这种情况,尤其是当它适用于“模型”属性(或我尝试过的其他属性,例如 currentText)时。尽管如此,我也尝试将 myCombo.currentIndex = testClassInstance.test_index 放入 onCurrentIndexChanged 中,但这并没有帮助(而且它似乎不正确...)。

我的问题:currentIndex 属性有什么特别之处吗?如何在不求助于在 qml 中显式定义信号连接的情况下实现我想要的(我认为这基本上就是 Q_PROPERTY 宏的用途)?我想我可以想出一些解决方法来实现我的目标,所以这不是我在这里寻找的 - 相反,我更希望有人能向我解释为什么这种特殊方法没有按我预期的方式工作。

主.qml

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Dialogs 1.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")


    MainForm {
        objectName: "mainForm"
        anchors.fill: parent
    }
}

主窗体.qml

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1

Item {
   width: 640
   height: 480


   Rectangle {
      anchors.centerIn: parent

      ComboBox {
            id: myCombo
            model: testClassInstance.test_list
            currentIndex: testClassInstance.test_index
            visible: true
            onCurrentIndexChanged: {
                testClassInstance.test_index = myCombo.currentIndex
            }
       }
   }
}

测试类.h

#ifndef TESTCLASS_H
#define TESTCLASS_H

#include <QObject>

class testClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int test_index READ getIndex WRITE setIndex NOTIFY notification)
    Q_PROPERTY(QStringList test_list READ getList WRITE setList NOTIFY notification)

public:
    testClass(QObject *parent) : QObject(parent) {}
    ~testClass() {}

    void modifyValues()
    {
        test_list << "1" << "2" << "3";
        notification();
        test_index = 2;
        notification();
    }

    int getIndex() { return test_index;  }
    QStringList getList() { return test_list;   }

    void setIndex(int val) { test_index = val;  }
    void setList(QStringList val) { test_list = val; }

signals:
    void notification();

private:
    int test_index = 0;
    QStringList test_list = QStringList("0");

};

#endif

主要.cpp

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;

    testClass test(&engine);
    engine.rootContext()->setContextProperty("testClassInstance", &test);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    test.modifyValues();

    return app.exec();
}

最佳答案

让我们分步进行:

1) 您创建组合框对象并将其属性(索引和模型)绑定(bind)到类的属性

2) 你调用 modifyValues 和 a)更改列表,这会触发模型更改 b) 改变索引,这会触发……什么都没有

问题出在步骤 2a 上。 ComboBox里面有如下代码:

onModelChanged: {
    ...
    popup.__selectedIndex = 0
}

此调用会破坏您对索引的绑定(bind),因此当您转到步骤 2b 时,绑定(bind)不再存在。

这是您问题的解决方案,您应该在模型更改后更新绑定(bind):

onModelChanged: {
     currentIndex = Qt.binding( function(){return testClassInstance.testIndex} )
}

关于c++ - QML 绑定(bind)整数属性 - C++ 中的更改未发送到 QML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35641874/

相关文章:

c++ - 如何在原生 C++ 中使用 QML 绘制二维码

c++ - 如何使用 C++ API 获取 QML 对象的 id 属性

c++ - lib(发布)或 libd(调试),Qt 可以为我解决这个问题吗?

QtQuick 2 透明窗口背景

c++ - 不使用三角函数旋转 vector

c++ - 使用 VC++ 的 VS2005 上的链接器问题

c++ - 这个 C++ 头文件的布局方式有什么问题吗?

c++ - 通过 Luabind 将 STL 队列暴露给 Lua

qt - 在 QML Webview 中使用相对 url

c++ - 验证 QCheckBox stateChanged?