I am new to QtQuick controls, I would like to create a simple GUI and I have encountered the following problem with binding certain c++ variables to qml widgets properties: In the simplified example below, I have a single combobox for which I would like to assign a list of items and also be able to set which item is selected from within the c++ side of the application.
For the test_list/model pair everything is working exactly as I would expect, but for the test_index/currentIndex it is not. After the test_index is set to 2 and notification is called, nothing happens - I expect that the READ method (getIndex) should be called, but it is not (it is for the test_list though). Changing the index from the GUI works, i.e. the value is sent from the qml to the c++ side due to the onCurrentIndexChanged, but it does not work the other way around. So after calling the modifyValues(), there are four items in the combobox - 0, 1, 2, 3 - but the currentIndex is still 0, so the "0" item is selected (meanwhile, test_index is equal to 2).
Odd thing is that the getIndex does get called the first time the widget is created. I have read that changing a property in the qml will terminate all the declarative bindings, but I do not see why this should happen here, especially when it works for the 'model' property (or other that I tried, e.g. currentText). Nevertheless, I have tried to put myCombo.currentIndex = testClassInstance.test_index
to the onCurrentIndexChanged as well, but that does not help (and it does not seem right...).
My questions: Is there something special about the currentIndex property? How to achieve what I want without resorting to explicitly defining signal connections in the qml (I thought that this is basically what the Q_PROPERTY macro is for)? I think I could figure out some workarounds to get to my goal, so that is not what I am looking for here - instead, I would prefer if somebody could explain to me why this particular approach is not working the way I expect.
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();
}