0

我是 QtQuick 控件的新手,我想创建一个简单的 GUI,并且在将某些 c++ 变量绑定到 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 中的属性将终止所有声明性绑定,但我不明白为什么会在这里发生这种情况,尤其是当它适用于“模型”属性(或我尝试过的其他属性,例如 currentText)时。尽管如此,我也尝试将myCombo.currentIndex = testClassInstance.test_indexonCurrentIndexChanged 放入,但这无济于事(而且它似乎不正确......)。

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

main.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
    }
}

MainForm.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

主文件

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();
}
4

2 回答 2

2

让我们分步进行:

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

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

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

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

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

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

onModelChanged: {
     currentIndex = Qt.binding( function(){return testClassInstance.testIndex} )
}
于 2016-02-26T16:36:49.740 回答
0

作为快速回复,您可以使用Connections,

   ComboBox {
       id: myCombo
       model: testClassInstance.test_list
       visible: true
       onCurrentIndexChanged: {
           testClassInstance.test_index = myCombo.currentIndex
       }
       Connections {
           target: testClassInstance
           onNotification: myCombo.currentIndex = test_index;
       }
   }
于 2016-02-26T10:22:07.317 回答