Attached properties in QML - c++

Can I create my own attached for everything property like a Component?
Item{
Component.onCompleted : {} // Component is attached to everyone Items
}

Yes, for example:
#include <QQmlEngine>
#include <QTimer>
class TestAttached : public QObject
{
Q_OBJECT
// Declare property with setter and getter
Q_PROPERTY(int val READ getVal WRITE setVal)
public:
TestAttached() Q_DECL_EQ_DEFAULT;
explicit TestAttached(QObject *parent):
QObject{parent},
m_val{100500}
{
Q_ASSERT(parent);
qDebug() << "* We just have created the object of attached properties for" << parent->metaObject()->className();
}
~TestAttached() Q_DECL_EQ_DEFAULT;
// define static function qmlAttachedProperties(QObject *object)
// which returns pointer to instance of TestAttached class
static TestAttached *qmlAttachedProperties(QObject *object)
{
TestAttached* testAttached { new TestAttached{object} };
QTimer* timer { new QTimer{testAttached} };
connect(timer, &QTimer::timeout,
[testAttached] {
testAttached->setVal(testAttached->getVal()+1);
emit testAttached->testDone(testAttached->getVal());
});
timer->start(3000);
return testAttached;
}
inline int getVal() const
{
return m_val;
}
inline void setVal(int val)
{
m_val = val;
}
signals:
void testDone(int val);
private:
int m_val;
};
// Makes the type TestAttached known to QMetaType (for using with QVariant)
QML_DECLARE_TYPE(TestAttached)
// declares that the TestAttached supports attached properties.
QML_DECLARE_TYPEINFO(TestAttached, QML_HAS_ATTACHED_PROPERTIES)
Register attached type in QML system (e.g. at main.cpp):
qmlRegisterUncreatableType<TestAttached>("my.test", 1, 0, "Test", QObject::tr("Test is an abstract type that is only available as an attached property."));
And try it in main.qml:
import QtQuick 2.15
import QtQuick.Window 2.15
//import our module
import my.test 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World of Attached properties")
Rectangle {
color: focus ? Qt.lighter("red") : "red"
width: parent.width/2; height: parent.height
anchors.left: parent.left
Component.onCompleted: {
console.log("Rectangle is completed", Test.val)
}
Keys.onReturnPressed: {
console.log("Rect 1: Attachet value is", Test.val)
}
Test.val: 20000
Test.onTestDone: function(num) {
console.log("We received", num, "from attached object")
}
MouseArea {
anchors.fill: parent
onClicked: parent.focus = true
}
}
Rectangle {
color: focus ? Qt.lighter("blue") : "blue"
width: parent.width/2; height: parent.height
anchors.right: parent.right
focus: true
Keys.onReturnPressed: {
// The attached object will created after return pressed
console.log("Rect 2: Attachet value is", Test.val)
}
MouseArea {
anchors.fill: parent
onClicked: parent.focus = true
}
}
}

You may not be able to attach properties to Items or Components you did not create. But why would you want to do that anyway?
Instead you could consider using signals and global properties.
For global properties that you can access from anywhere you can set the context property of the root context of the declarative view.
i.e,
QmlApplicationViewer viewer;
MyPropertyClass myProp;
viewer->rootContext()->setContextProperty("MyPropClass", &myProp);
Now, in your QML file you can access the properties of this class as
Rectangle {
Text {
text: MyPropClass.getMyPropText()
}
MouseArea {
onClicked: { MyPropClass.text = "Clicked" }
}
}
This will invoke the Q_INVOKABLE method getMyPropText() from the MyPropertyClass. and Q_PROPERTY 'text' can be set when some signal is emitted.
Would this suit you needs?

Related

Advice to importing a list with instances of a class from c++ to qml in runtime

I have a QList where each element is a instance of a c++ class. These instances contain information and based on that I want to create and move rectangles in QML. The contained information is the x position (among other things) and I want to create/move one rectangle per element in the QList. The QList gets updated in periodic intervals in runtime, meaning some elements can get added, removed or the x position edited.
I programmed a small example to understand how to accomplish the bridge between c++ and QML, but I think my code will only work once as a initialization and not if I update the QList in runtime. Am I on the right track and if not, what do I have to change? Is it necessary to use QAbstractListModel like suggested in the answers to this question by Timmmm?
Here's my code:
class.h:
#ifndef CLASS_H
#define CLASS_H
#include <QQuickItem>
class RectangelClass : public QObject
{
private:
Q_OBJECT
Q_PROPERTY(int xPos READ xPos WRITE setXPos NOTIFY xPosChanged)
int m_xPos;
public:
RectangelClass () {}
int xPos() const { return m_xPos; }
public slots:
void setXPos(int arg)
{
if (m_xPos == arg)
return;
m_xPos = arg;
emit xPosChanged(arg);
}
signals:
void xPosChanged(int arg);
};
class RectangelClassManager : public QObject
{
private:
Q_OBJECT
Q_PROPERTY(QList <QObject*> rectangelClassList READ rectangelClassList WRITE setRectangelClassList NOTIFY rectangelClassListChanged)
QList <QObject*> m_rectangelClassList;
public:
RectangelClassManager ()
{
QList <QObject*> localObjList;
for (int i = 0; i < 5; i++)
{
RectangelClass *localObj = new RectangelClass();
localObj->setXPos (i*100);
localObjList.push_back(localObj);
}
setRectangelClassList (localObjList);
}
QList <QObject*> rectangelClassList () const { return m_rectangelClassList; }
public slots:
void setRectangelClassList (QList <QObject*> arg)
{
if (m_rectangelClassList == arg)
return;
m_rectangelClassList = arg;
emit rectangelClassListChanged(arg);
}
signals:
void rectangelClassListChanged (QList <QObject*> arg);
};
#endif // CLASS_H
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "class.h"
#include <iostream>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<RectangelClass>("cppclasses", 1, 0, "RectangelClass");
qmlRegisterType<RectangelClassManager>("cppclasses", 1, 0, "RectangelClassManager");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
main.qml:
import QtQuick 2.4
import QtQuick.Window 2.2
import cppclasses 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
RectangelClassManager{
id: rectangelClassManager
}
Rectangle{
id: rect0
x: rectangelClassManager.rectangelClassList[0].xPos
y: 100
width: 80
height: 80
color:"yellow"
Text {
id: textid0
anchors.centerIn: parent
text: "X-Position: " + rectangelClassManager.rectangelClassList[0].xPos
}
}
Rectangle{
id: rect1
x: rectangelClassManager.rectangelClassList[1].xPos
y: 100
width: 80
height: 80
color:"yellow"
Text {
id: textid1
anchors.centerIn: parent
text: "X-Position: " + rectangelClassManager.rectangelClassList[1].xPos
}
}
Rectangle{
id: rect2
x: rectangelClassManager.rectangelClassList[2].xPos
y: 100
width: 80
height: 80
color:"yellow"
Text {
id: textid2
anchors.centerIn: parent
text: "X-Position: " + rectangelClassManager.rectangelClassList[2].xPos
}
}
Rectangle{
id: rect3
x: rectangelClassManager.rectangelClassList[3].xPos
y: 100
width: 80
height: 80
color:"yellow"
Text {
id: textid3
anchors.centerIn: parent
text: "X-Position: " + rectangelClassManager.rectangelClassList[3].xPos
}
}
Rectangle{
id: rect4
x: rectangelClassManager.rectangelClassList[4].xPos
y: 100
width: 80
height: 80
color:"yellow"
Text {
id: textid4
anchors.centerIn: parent
text: "X-Position: " + rectangelClassManager.rectangelClassList[4].xPos
}
}
}
Edit to make my question more clear:
Is it possible to update the QList in runtime in c++, will it be updated in QML and if not, how do I achieve that instead.
Yes a QList property can be updated in runtime by emitting the rectangelClassListChanged() signal. However, this can be very ineffecient, since the whole list is reparsed. So, depending on how often your QList changes, you might be better of changing it to a QAbstractListModel.
Also, you can change your code to use a Repeater, it hurts my programmer-eyes ;-) and it might actually be the cause of not updating runtime.
import QtQuick 2.4
import QtQuick.Window 2.2
import cppclasses 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
RectangelClassManager{
id: rectangelClassManager
}
Repeater {
model: rectangelClassManager.rectangelClassList
delegate: Rectangle {
x: modelData.xPos
y: 100
width: 80
height: 80
color:"yellow"
Text {
id: textid0
anchors.centerIn: parent
text: "X-Position: " + modelData.xPos
}
}
}
}

Access an QObject class from another QObject class by reference and parallel using in qml [duplicate]

I tried to operate a part of a qt project in Qt\Examples\Qt-5.9\quick\views, I am new to qml and I am trying to open each time a different QDialog window depending on qml pathview component that has been clicked. First of all, I started with creating a class (interfacageQML) which will serve to interface the qml Mainform and the QDialog (qtinterface), the necessary files are included among which interfacageqml.h.
here is the main.cpp :
#include "interfacageqml.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<interfacageQML>("Interfacage", 1, 0,"Component:MouseArea");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
And here's interfacageqml.h :
#ifndef INTERFACAGEQML_H
#define INTERFACAGEQML_H
#include <QObject>
#include "qtinterface.h"
class interfacageQML : public QObject
{
Q_OBJECT
public:
interfacageQML(QObject *parent);
~interfacageQML();
Q_INVOKABLE void mouseClick();
signals:
void clicked();
};
#endif // INTERFACAGEQML_H
interfacageqml.cpp :
#include "interfacageqml.h"
#include <QDebug>
#include <QApplication>
interfacageQML::interfacageQML(QObject *parent)
: QObject(parent)
{
}
interfacageQML::~interfacageQML()
{
}
void interfacageQML::mouseClick()
{
qDebug() << "qmlinterface::mouseClick()";
emit clicked();
}
My project is organised this way :
the qmlinterface.qrc file contains these paths:
main.qml :
import QtQuick 2.6
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MainForm{
anchors.fill: parent
}
}
MainForm.qml :
import QtQuick 2.6
import QtQuick.Controls 2.0 as QQC2
import Interfacage 1.0
Rectangle {
width: 800
height: 800
color: "white"
ListModel {
id: appModel
ListElement {
name: "Contacts"
icon: "pics/Resources/AddressBook_48.png"
}
ListElement {
name: "Music"
icon: "pics/Resources/AudioPlayer_48.png"
}
ListElement {
name: "Movies"
icon: "pics/Resources/VideoPlayer_48.png"
}
ListElement {
name: "Camera"
icon: "pics/Resources/Camera_48.png"
}
ListElement {
name: "Calendar"
icon: "pics/Resources/DateBook_48.png"
}
ListElement {
name: "Todo List"
icon: "pics/Resources/TodoList_48.png"
}
}
Component {
id: appDelegate
Item {
width: 100
height: 100
scale: PathView.iconScale
Image {
id: myIcon
y: 20
anchors.horizontalCenter: parent.horizontalCenter
source: icon
}
Text {
anchors {
top: myIcon.bottom
horizontalCenter: parent.horizontalCenter
}
text: name
}
MouseArea {
anchors.fill: parent
onClicked: {
view.currentIndex = index
Interfacage.mouseClick
}
}
}
}
Component {
id: appHighlight
Rectangle {
width: 100
height: 80
color: "lightsteelblue"
}
}
PathView {
id: view
anchors.fill: parent
highlight: appHighlight
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
focus: true
model: appModel
delegate: appDelegate
path: Path {
startX: 50
startY: 80
PathAttribute {
name: "iconScale"
value: 2.0
}
PathQuad {
x: 250
y: 200
controlX: 50
controlY: 200
}
PathAttribute {
name: "iconScale"
value: 2.0
}
PathQuad {
x: 600
y: 50
controlX: 400
controlY: 200
}
PathAttribute {
name: "iconScale"
value: 2.0
}
}
}
}
When I run this project, i got an error :
error:C2280
However, when I comment this line : qmlRegisterType<interfacageQML>("Interfacage", 1, 0, "Component:MouseArea"); the project runs and I can navigate between the pathview components in the MainForm.
When you use qmlRegisterType you are registering a new data type in QML, it is not an object, in that case the name "Component: MouseArea" is not suitable.
qmlRegisterType<interfacageQML>("Interfacage", 1, 0, "InterfacageQML");
Another error is that you must pass a parent by default, in this case 0 or nullptr since the items may not have parents.
class interfacageQML : public QObject
{
Q_OBJECT
public:
explicit interfacageQML(QObject *parent = nullptr);
[...]
As I said in the first lines, this is a new type, it is not an object so you must create it.
import QtQuick 2.6
import QtQuick.Controls 2.0 as QQC2
import Interfacage 1.0
Rectangle {
width: 800
height: 800
color: "white"
InterfacageQML{
id: myitem
}
[...]
And in the end if you want to use it you must call the function through the item.
MouseArea {
anchors.fill: parent
onClicked: {
view.currentIndex = index
myitem.mouseClick()
}
}
Since you want to connect your QDialog with the QML through that class, you can not do it since they will be different objects, one solution for this is to use a singleton, for this you must do the following:
interfacageqml.h
#ifndef INTERFACAGEQML_H
#define INTERFACAGEQML_H
#include <QObject>
#include <QQmlEngine>
class interfacageQML : public QObject
{
Q_OBJECT
static interfacageQML* instance;
explicit interfacageQML(QObject *parent = nullptr);
public:
static interfacageQML *getInstance();
~interfacageQML();
Q_INVOKABLE void mouseClick();
signals:
void clicked();
};
#endif // INTERFACAGEQML_H
interfacageqml.cpp
#include "interfacageqml.h"
#include <QDebug>
interfacageQML* interfacageQML::instance = 0;
interfacageQML *interfacageQML::getInstance()
{
if (instance == 0)
instance = new interfacageQML;
return instance;
}
interfacageQML::interfacageQML(QObject *parent) : QObject(parent)
{
}
interfacageQML::~interfacageQML()
{
}
void interfacageQML::mouseClick()
{
qDebug() << "qmlinterface::mouseClick()";
emit clicked();
}
main.cpp
#include "interfacageqml.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
static QObject *singletonTypeProvider(QQmlEngine *, QJSEngine *)
{
return interfacageQML::getInstance();
}
int main(int argc, char *argv[])
{
qmlRegisterSingletonType<interfacageQML>("Interfacage", 1, 0, "InterfacageQML", singletonTypeProvider);
// test
interfacageQML *obj = qobject_cast<interfacageQML*>(interfacageQML::getInstance());
QObject::connect(obj, &interfacageQML::clicked,[]{
qDebug()<<"clicked";
});
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
As it is a singleton it is not necessary to create an item, you can do it directly:
import Interfacage 1.0
[...]
MouseArea {
anchors.fill: parent
onClicked: {
view.currentIndex = index
InterfacageQML.mouseClick()
}
}
This last example can be found in the following link.

Accessing/modifying all instances of a type in Qt/QML

In QML, I have a custom object type (a separate QML file) and I would like a way of accessing and/or modifying each instance of this type. For a very simple example:
MyText.qml:
Text {
height: 100
width: 100
color: "red"
function logStuff() {
console.log("This is MyText")
}
}
SomePage.qml:
MyText {
id: text1
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
text: "foo"
}
MyText {
id: text2
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: "bar"
}
When an event occurs (e.g. a button on SomePage.qml being clicked or a signal being emitted), I would like to be able to change all instances of MyText to have the same value for one property, or call each MyText's logStuff() function.
Note: in my actual use case, there are actually several dozen of these instances, and there will be other Text elements which are not instances of MyText.
I have a little experience with jQuery and was hoping there would be something similar to jQuery selectors, but I have been unable to find anything remotely similar. Either a QML or a C++ (or mixed) solution would be fine.
I would like to suggest a method using C++.
Since there is no way to get base class of QML object you can base the searching on objectName property witch is accessible in C++.
Suppose we have base QML object:
import QtQuick 2.3
Item {
id: base
objectName: "BaseItem"
property int someValue: 0
onSomeValueChanged: {
console.log("'someValue' was changed to " + someValue + " for " + base);
}
}
And another QML file, where these objects are used:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
visible: true
width: 300
height: 300
id: mainWindow
Base {
id: derived1
}
Base {
id: derived2
}
Base {
id: derived3
}
}
The idea is that all derived object inherit the same objectName from the base class.
So now you can simply find all of the objects in C++:
QObject *root = engine.rootObjects().first();
QList<QObject *> list = root->findChildren<QObject *>("BaseItem");
qsrand(QTime::currentTime().msec());
foreach(QObject *item,list) {
item->setProperty("someValue",qrand());
}
Here I just change the property but you also can call some method with QMetaObject::invokeMethod() etc.
I'm not sure to understand your need but I would just use a Connections element like so :
SomePage.qml:
MyText {
id: text1
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
text: "foo"
Connections {
target: senderItemId
onFooChanged: logStuff()
}
}
MyText {
id: text2
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: "bar"
Connections {
target: senderItemId
onFooChanged: logStuff()
}
}
There's no API call in Qt to do this (that I could find), but you can find all the QML QObject's by a type using QObject::children() and QMetaObject in C++. Below is an implementation example.
QList<QObject *> MySingleton::findObjectsOfComponent(QObject *parent, QQmlComponent *component) const
{
auto object = component->create(QQmlEngine::contextForObject(parent));
auto foundObjects = findObjectsOfObject(parent, object);
delete object;
return foundObjects;
}
QList<QObject *> MySingleton::findObjectsOfObject(QObject *parent, const QObject *object) const
{
auto className = object->metaObject()->className();
QList<QObject*> items;
for(auto child : parent->children()) {
if(child->metaObject()->className() == className) {
items.append(child);
}
items.append(findObjectsOfObject(child, object));
}
return items;
}
Then you should register MySingleton as a QML singleton and use a Component to find the type.
Component {
id: errorLabelComponentId
ErrorLabel {}
}
Button {
onClicked: {
//Un-ignore all error labels
var errorLabels = MySingleton.findObjectsOfComponent(pageId, errorLabelComponentId)
for(var i in errorLabels) {
//ignoreError is a property of ErrorLabel {}
errorLabels[i].ignoreError = false
}
}
}

Binding C++ to QML code when using Components

---edited url and changed dynamic part to something compilable----
(Using Qt 5.3)
I tried to create a compact sample, but its still too big to post all the files here separately, so i added a link to "uploaded.to" as i cannot seem to attach a zip file here :-((
(warning, spam links and / or waiting time, any better fileshare site you recommend ?
Here is a link to "bindtest.zip" via uploaded.com, beware of spam/ugly pix:
http://ul.to/lqemy5jx
Okay, i will try to post the essence of the files here anyways:
I tried to create a simple Class in C++ containing a StringList and an index.
I Instantiated two Objects of this Class and exposed them via "setContextProperty"
This should be used in QML to initialize a ListView and to be in sync with it.
So whenever a User changes the index in QML, C++ should be notified AND vice versa.
So when i create two Component qml files using the hardwired names set in "setContextProperty" it seems to work fine.
But for the life of me i cannot create a single component file and pass the DataObject to it as a parameter, i simply do not know how to do it, although i tried.
My "final" target ist to create a QML Object dynamically and pass the DataObject to it, this does not work either :-(
So here it comes, code snippets of my sample Project:
Declaring my oh-so-simple Class (DataObject.h)
#ifndef DATAOBJECT_H
#define DATAOBJECT_H
#include <QObject>
#include <QDebug>
class DataObject : public QObject
{
Q_OBJECT
Q_PROPERTY( int index MEMBER m_index NOTIFY indexChanged )
public slots:
int count() const { return m_Elements.count(); }
QString at(int idx) const { return m_Elements.at(idx); }
public:
void setIndex(int theInt) { m_index = theInt; }
signals:
void indexChanged(int);
public: // too lazy to write accessors for this sample, so make it public
QStringList m_Elements;
private:
int m_index;
};
#endif // DATAOBJECT_H
Registering it in main.cpp:
qmlRegisterType<DataObject>("bindtestTypes", 1, 0, "DataObject");
Here is the part of "dialog.cpp" that initializes and exposes two DataObects:
//preparing first list
m_firstDO.m_Elements = QStringList() << "A" << "B" << "C" << "D";
m_firstDO.setIndex(0);
//preparing second list
m_secondDO.m_Elements = QStringList() << "a" << "b" << "c" << "d";
m_secondDO.setIndex(3);
//publish the 2 Dataobjects
m_engine.rootContext()->setContextProperty( "cppDataList_1", &m_firstDO);
m_engine.rootContext()->setContextProperty( "cppDataList_2", &m_secondDO);
Here is the QML file "ShowLists.qml" that should simply show the 2 ListVies on Top of each other, i commented the 2 NOT working approaches that i would love to work, especially the dynamic one:
import QtQuick 2.2
import QtQuick.Window 2.1
import bindtestTypes 1.0
Window {
visible: true
width: 200
height: 400
Rectangle{
anchors.fill: parent
//dynamic: does not work :-(
// need to click on it to create it
// Rectangle{
// id:upperList
// anchors.top: parent.top;
// anchors.left: parent.left
// width:200
// height:200
// MouseArea{
// anchors.fill: parent
// onClicked: {
// var component = Qt.createComponent("SimpleList.qml");
// var dyncbb = component.createObject(parent, {"theDO": cppDataList_1});
// }
// }
// }
// Rectangle{
// id:lowerList
// anchors.bottom: parent.bottom;
// anchors.left: parent.left
// width:200
// height:200
// MouseArea{
// anchors.fill: parent
// onClicked: {
// var component = Qt.createComponent("SimpleList.qml");
// var dyncbb = component.createObject(parent, {"theDO": cppDataList_2});
// }
// }
// }
//static: would not be my first choice but isnt working anyways...
// SimpleList {
// id:upperList
// property DataObject theDO: cppDataList_1
// anchors.top: parent.top;
// anchors.left: parent.left
// }
// SimpleList {
// id:lowerList
// property DataObject theDO: cppDataList_2
// anchors.bottom: parent.bottom;
// anchors.left: parent.left
// }
//hardwired works, but its not workable for my rather complex project...
SimpleList1 {
id:upperList
anchors.top: parent.top;
anchors.left: parent.left
}
SimpleList2 {
id:lowerList
anchors.bottom: parent.bottom;
anchors.left: parent.left
}
}
}
Here is the first hardwired SimpleList1.qml that works fine, as well as the second:
import QtQuick 2.2
ListView {
id: list_view
width: 200
height: 200
currentIndex: cppDataList_1.index
model: cppDataList_1.count()
delegate: Rectangle {
height: 20
width: 200
Text { text: cppDataList_1.at(index); color: (list_view.currentIndex === index)?"red":"black" }
MouseArea{ anchors.fill: parent; onClicked: list_view.currentIndex = index }
}
onCurrentIndexChanged: cppDataList_1.index = currentIndex;
}
This is the "SimpleList.qml" that i cannot seem to get to work:
import QtQuick 2.2
import bindtestTypes 1.0
Rectangle {
ListView {
id: list_view
property DataObject theDO
width: 200
height: 200
currentIndex: theDO.index
model: theDO.count()
delegate: Rectangle {
height: 20
width: 200
Text { text: theDO.at(index); color: (list_view.currentIndex === index)?"red":"black" }
MouseArea{ anchors.fill: parent; onClicked: list_view.currentIndex = index }
}
onCurrentIndexChanged: theDO.index = currentIndex
}
}
So, can anyone of you help me to get this solved ??
IF you dare to follow the uploaded link and run my sample you can see one more glitch.
It displays 2 Windows, one QQQuickWIndow and a Widget.
In the Widget i can change the indexes as well as in the QML Window.
At first they are in sync but then the QML Window does not get updated anymore by changing the index in the widget, i hope its a glitch and not another general error i made.
Greetings & thanks for any help !
Nils
Argh, i found the problem, i did a very simple mistake:
The property i want to set in the SimpleList Component has to be in the root Object, so instead of this:
Rectangle {
ListView {
id: list_view
property DataObject theDO
...
It has to be done this way:
Rectangle {
property DataObject theDO
ListView {
id: list_view
...
Wow, thats an easy solution for a (seemingly) complex Problem.
Greetings,
Nils

QQuickWidget and C++ interaction

I am experiencing with the new QQuickWidget. How can I interact between the QQuickWidget and C++?
C++
QQuickWidget *view = new QQuickWidget();
view->setSource(QUrl::fromLocalFile("myqml.qml"));
view->setProperty("test", 0);
myLayout->addWidget(view);
QML
import QtQuick 2.1
Rectangle {
id: mainWindow
width: parent.width
height: parent.height
Text {
id: text
width: mainWindow.width
font.pixelSize: 20
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: test
}
}
text: test does not work: ReferenceError: test is not defined
How can I give my QML file some properties via C++?
Is it also possible to get the Text object in C++ and update its text?
Give it a try:
view->rootContext()->setContextProperty("test", "some random text");
instead of
view->setProperty("test", 0);
setProperty(name, val) works if object has the property name defined as Q_PROPERTY.
It is possible to pass QObject-derived object as view's context property:
class Controller : public QObject
{
Q_OBJECT
QString m_test;
public:
explicit Controller(QObject *parent = 0);
Q_PROPERTY(QString test READ test WRITE setTest NOTIFY testChanged)
QDate test() const
{
return m_test;
}
signals:
void testChanged(QString arg);
public slots:
void setTest(QDate arg)
{
if (m_test != arg) {
m_test = arg;
emit testChanged(arg);
}
}
};
Controller c;
view->rootContext()->setContextProperty("controller", &c);
Text {
id: text
width: mainWindow.width
font.pixelSize: 20
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: controller.test
}
Is it also possible to get the Text object in C++ and update its text?
In general, it doesn't seem to be the best approach -- c++ code shouldn't be aware of presentation if it follows model-view pattern.
However it is possible as described here.