2016-02-26 101 views
0

我是QtQuick控件的新手,我想創建一個簡單的GUI,並遇到以下問題,將某些C++變量綁定到qml小部件屬性: 下面簡單的例子,我有一個單獨的組合框,我想分配一個項目列表,並且能夠設置從應用程序的C++端選擇哪個項目。QML綁定整型屬性 - C++中的更改未發送到QML

對於test_list/model對,一切正如我所料,但對於test_index/currentIndex它不是。在test_index被設置爲2並且調用通知之後,沒有任何事情發生 - 我期望應該調用READ方法(getIndex),但它不是(它是針對test_list的)。由於onCurrentIndexChanged,更改GUI的索引工作,即從qml發送到C++端,但它不會以其他方式工作。因此,在調用modifyValues()之後,組合框中有四項 - 0,1,2,3 - 但currentIndex仍然爲0,所以選擇了「0」項(同時,test_index等於2)。

奇怪的是getIndex在第一次創建窗口小部件時被調用。我已經讀過在qml中更改屬性將終止所有聲明性綁定,但我不明白爲什麼會發生這種情況,特別是當它適用於'model'屬性(或其他我試過的,例如currentText)時。儘管如此,我還試圖將myCombo.currentIndex = testClassInstance.test_index也添加到onCurrentIndexChanged中,但這並沒有幫助(它看起來不正確...)。

我的問題: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 
      } 
     } 
    } 
} 

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

的main.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(); 
} 

回答

2

讓斷裂的步驟:

1)創建ComboBox對象,並將其綁定的屬性(指數型),以類的屬性

2)您調用modifyValues和 a)更改列表,這會觸發模型更改 b)更改索引,這會觸發...什麼也沒有

問題出在步驟2a。組合框裏面有以下代碼:

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

這個調用你能否指數結合,所以當你轉到步驟2B,結合不存在了。

這裏是解決你的問題,你應該updage結合後的模型發生變化:

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

哦......這實際上是有道理的。我不得不說,即使我自己意識到這一點,我不認爲我會弄清楚我必須使用'Qt.binding(...)'語法而不是像'currentIndex: test_index',這看起來很不直觀,我沒有看到在我遇到的任何教程中使用過...儘管如此,非常感謝您的解釋和解決方案。 – tomj

+0

無論何時您編寫信號處理程序代碼,它都是javascript,並且簡單分配不會作爲綁定工作,因此您必須顯式創建綁定。 –

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; 
     } 
    } 
+0

你好,謝謝,這個解決方案是工作(我真正嘗試過之前,只是不知道我有在那裏指定「onNotification:」)。無論如何,我仍然想知道爲什麼我必須爲currentIndex執行此操作,但我不需要爲「model」,「currentText」或其他一組屬性執行此操作;這對我來說很困惑。如果有人(或者你有時間)可以解釋,我會等幾天,如果沒有人,我會將你的答案標記爲已接受。 – tomj

+0

你好,你可以隨時諮詢Qt文檔。他們有據可查。它已經在這裏描述,http://doc.qt.io/qt-5/qml-qtquick-controls-combobox.html#model-prop – cavitsinadogru

+0

我已經閱讀過,但問題是「改變模型後初始化會將currentIndex重置爲0.「在我眼中並不意味着綁定到另一個變量會被打破。我期望根據這句話,currentIndex將被設置爲0,並且綁定到它的變量也將被設置爲0.現在我已經知道這不是它的工作方式(當它需要更多時時間考慮它),但我之前沒有意識到。也許值得明確提及那些「缺乏經驗」的人的「突破綁定」問題。 – tomj