Passing values from C++ to QML...
-
I have a problem, when I call from C++ code:
@
object->setProperty("width", viewer.width());
@
or:
@
object->setWidth(viewer.width());
@
I am not able to access this values from QML (at least I have tried it in "constructor" (Component.onCompleted)) - but if I call this property on destroying, it works... I don't understand that... -
Hi,
Can you provide a larger snippet showing e.g. where/how object is created? Perhaps Component.onCompleted is being fired before the width is changed.
Regards,
Michael -
Yes, sure...
@
MainWindow
{
id: mainWindowwidth: 100 height: 100 Component.onCompleted: { console.log("Fired!" + mainWindow.screenWidth); // does not work. } Component.onDestruction: { console.log("Fired!" + mainWindow.screenWidth); // works. } Rectangle { x: 10; y: 10; width: 50; height: 50; color: "red"; Component.onCompleted: { console.log(mainWindow.screenHeight) } }
}
@
Where MainWindow is just basic QDeclarativeItem class:
@
#include <QObject>
#include <QDeclarativeItem>class MainWindow : public QDeclarativeItem
{
Q_OBJECT
Q_PROPERTY(int screenWidth READ getScreenWidth WRITE setScreenWidth NOTIFY screenWidthChanged)
Q_PROPERTY(int screenHeight READ getScreenHeight WRITE setScreenHeight NOTIFY screenHeightChanged)public:
explicit MainWindow(QDeclarativeItem *parent = 0);Q_INVOKABLE int getScreenWidth(void) { return window.x(); }
void setScreenWidth(int w) { window.setX(w); }Q_INVOKABLE int getScreenHeight(void) { return window.y(); }
void setScreenHeight(int h) { return window.setY(h); }signals:
void screenWidthChanged(int width);
void screenHeightChanged(int height);public slots:
protected:
private:
QPoint window;
};
@
And passing to it, in main function:
@
MainWindow* mainWindow = qobject_cast<MainWindow*> (viewer.rootObject());mainWindow->setProperty("screenWidth", viewer.width()); mainWindow->setProperty("screenHeight", viewer.height());
@
where viewer is QDeclarativeView... -
It's setting the properties, but realize that the Component.onCompleted is going to be called long before you can do things like viewer.rootObject() -- the QML components are completed at the line where you load a QML file into the viewer. The C++ cannot interact with a QML element that has not been created yet. If you want assurance that things are being set correctly as soon as the application starts (which they should be) then monitor the properties with something like this:
@MainWindow {
//...
onScreenWidthChanged: {
console.log ("screenWidth is now " + screenWidth);
}
}@Component.onCompleted will run before the C++ can interact with your object.
-
So, how to set variables from C++ in QML?
I am doing something wrong, because I want to run it as fullscreen, I just need a resolution of display in QML...
-
You are setting the QML properties from C++. But seriously, I think you're overcomplicating this. If you want to show your QML fullscreen, then when you show the viewer, use viewer.showFullscreen() instead of whatever it is you're currently using. The root object will automatically size to the viewer size.
-
Well, that's not true. Only graphics scene resizes, not the root object.
-
Well, it does in my experience (maybe I used anchors.fill: parent on root?), but I think you'd benefit from reading this: http://doc.qt.nokia.com/4.7-snapshot/qdeclarativeview.html#resizeMode-prop
-
Well, the truth is that, I have to write much more QML code (used for UI, not for the business logic) - I want to have in QML everything clean, and readble - I just want to pass the viewer's size inside into QML...
-
Well you'll have to forgive me because I'm a bit slow. You can set one flag from C++ in the very readable line
@viewer.setResizeMode(QDeclarativeView::SizeRootObjectToView);@
or you can subclass QDeclarativeItem, make new properties, pass values for these properties to QML from C++, debug everything.... and you expect this to be cleaner and more readable? Please understand that I don't mean to be condescending, but we seem to have very different ideas of what constitutes cleanliness and readability. :P
-
Well, okay, in QML you have to write:
@
Rectangle
{
id: root
height: 10
width: 100property int screenWidth: 0 property int screenHeight: 0 onWidthChanged: { screenWidth = width console.log(screenWidth) } onHeightChanged: { screenHeight = height console.log(screenHeight) } Rectangle { Component.onCompleted: { console.log("root's screen height: " + root.screenHeight) // writes: 0. } }
}
@Okay, it's fine - screenHeight, screenWidth are as my resolution, but the child item - rectangle depends on screenHeight/screenWidth which are the root's properties... could you change my thinking? Because I am thinking, I think, conversely.
-
I think these properties screenHeight and screenWidth need to go away. They make no sense; they seem to be copies of width and height.
Looking at your code there, this is the only code I see that actually seems useful:
@
Rectangle {
id: rootRectangle { //Whatever actually goes in this thing }
}
@From the C++, you can just set the root object to resize to the view like I showed earlier, do a viewer.showFullScreen() and be happy. :)
Oh, and stop using Component.onCompleted() to tell you what the sizes of things are. QML doesn't work that way -- components are completed, but after that changes continue propagating through until everything is set up the way it's supposed to be. Rendering a QML GUI is a multistep process that happens behind the scenes, don't expect onCompleted to have the final values of things. It will have the initial placeholders (most likely 0) that are used until everything is created and real values can be calculated.
Of course, my response is naive because I don't know what you're actually trying to put on the screen. If I had some idea of what you want your window to look like, I could give much more useful responses.