Dynamic size QML Page unable to render
-
Hello,
Description:
The Screen.Width function works for main.qml without issues.File main.qml
ApplicationWindow { id: mainWindow //Wide screen support //Screen.desktopAvailableWidth / 4 //Screen.desktopAvailableHeight / 6 //The below is monitor cross-compatible (phone, PC, laptop) width: Screen.width / 2 height: Screen.height / 3
Does it work? Yes.
It scales up and down, jut as I desire.When the ApplicationWindow is assigned an ID (unique ID I believe, no errors reported), then the Page 2 using that ID won't obtain the width and height of that window.
That's the first problem, but it could be related to the general issue (lack of dynamic sizing compatibility).
To work around this issue (in case that calling AppWindow would be somehow restricted), I simply used the same call (Screen.width, height) in the Page object in Page2Form.qml
The issue: it does not work. The Page renders (has got some sort of default properties that override the size settings), but when using Form Editor it doesn't have any size. The same method that works for AppWindow, doesn't work for page...
Let's make Page 2 fixed size:
It does work as I desire it to work. The text input object also calculates own width and height basing on the width and height of the local Page object (Page 2 in this case).
The Page 2 code:
The sample code:import QtQuick 2.9 import QtQuick.Controls 2.5 import QtQml 2.3 Page { id: localPage2 width: Screen.width / 2 height: Screen.height / 3 TextInput { id: textInput x: (localPage2.width / 2) - width / 2 y: (localPage2.height / 4) - height / 2 width: localPage2.width / 3 height: localPage2.height / 6 text: qsTr("Text Input") font.pixelSize: 12 } }
vs
Page { id: localPage2 width: 600 height: 600 TextInput { id: textInput x: (localPage2.width / 2) - width / 2 y: (localPage2.height / 4) - height / 2 width: localPage2.width / 3 height: localPage2.height / 6 text: qsTr("Text Input") font.pixelSize: 12 } }
Summary:
I want to use dynamic size by either call of Screen.width or (the best) call on size (width and height) of the ApplicationWindow.
In either case - they don't work, and I don't want to use fixed pixel size.
-
You are probably getting errors.
You need to import:import QtQuick.Window 2.2
https://doc.qt.io/qt-5/qml-qtquick-window-screen.html#details
-
You were right, at least it works in a way now. Not ideally though.
The following works:
import QtQuick 2.9 import QtQuick.Controls 2.5 import QtQuick.Window 2.3 import QtQml 2.3 Page { id: localPage2 width: Screen.width / 2 height: Screen.height / 3 TextInput { id: textInput x: (localPage2.width / 2) - width / 2 y: (localPage2.height / 4) - height / 2 width: localPage2.width / 3 height: localPage2.height / 6 text: qsTr("Text Input") font.pixelSize: 12 } }
this one doesn't
ApplicationWindow { id: mainWindow ...
Page { id: localPage2 width: mainWindow.width / 2 height: mainWindow.height / 3
-
They are not in the same file, as one is in the main.qml (application window)
and the other is a separate file, describing a new page that renders in that window.I followed this guide
https://doc.qt.io/qt-5/qtqml-syntax-objectattributes.htmlalong with other tips on the internet.
The thing is, I remember that when I wrote apps in C# with MetroGUI then I could easily "reference" objects by using their IDs. I can't see why I wouldn't be able to reference an object from a different QML file.Aren't they all (the QML files) compiled into a large QML file and then into C++ file, or (as one large file) linked to some pre-compiled libraries?
There isn't much beside what I have shown already.
I wrote this app at work, because I need something for ease of managing some of my stuff on desktop.main.qml
import QtQuick 2.9 import QtQuick.Controls 2.5 import QtQml 2.3 import QtQuick.Window 2.3 //Library for tray icon import Qt.labs.platform ApplicationWindow { id: mainWindow //Wide screen support //Screen.desktopAvailableWidth / 4 //Screen.desktopAvailableHeight / 6 //The below is monitor cross-compatible (phone, PC, laptop) width: Screen.width / 2 height: Screen.height / 3 visible: true title: qsTr("Redacted") //setWindowIcon(QIcon(":/path/to/icon.png")); //Tray icon object definition, show, raise, activate window on tray activation. SystemTrayIcon { visible: true icon.source: "qrc:/Icons/AppIcon.svg" onActivated: { ApplicationWindow.show() ApplicationWindow.raise() ApplicationWindow.requestActivate() } } SwipeView { id: swipeView anchors.fill: parent currentIndex: tabBar.currentIndex Page1Form { } Page2Form { } Page3Form { } } footer: TabBar { id: tabBar currentIndex: swipeView.currentIndex TabButton { text: qsTr("About") } TabButton { text: qsTr("Redacted") } TabButton { text: qsTr("Redacted") } } }
Page2Form.ui.qml
import QtQuick 2.9 import QtQuick.Controls 2.5 import QtQuick.Window 2.3 import QtQml 2.3 Page { id: localPage2 width: Screen.width / 2 height: Screen.height / 3 Rectangle { id: rectangle x: (localPage2.width / 2) - (width / 2) y: (localPage2.height / 4) - (height / 2) width: localPage2.width / 3 height: localPage2.height / 6 color: "#ffffff" border.color: "#a45c5c" border.width: 2 TextInput { id: textInput x: 0 y: 0 width: localPage2.width / 3 height: localPage2.height / 6 text: qsTr("Redacted") font.pixelSize: 12 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter font.weight: Font.Normal focus: true } } }
(im trying to put a text input into rectangle, as TextInput doesn't have a border property...)
otherwise it would look like
Page { id: localPage2 width: mainWindow.width / 2 height: mainWindow.height / 3 Rectangle { id: rectangle x: (localPage2.width / 2) - (width / 2) y: (localPage2.height / 4) - (height / 2) width: localPage2.width / 3 height: localPage2.height / 6 color: "#ffffff" border.color: "#a45c5c" border.width: 2
-
@Matthew0x said in Dynamic size QML Page unable to render:
mainWindow
You can only see ids in the same file. Yeah, it is kind of confusing at first.
-
Thank you for your help and information.
I have one question then. How can you reference objects outside of a specific QML file?
What if I want to change properties of an object in a different tab (Page) using controls or data in the previous one for example. -
@Matthew0x
Pass data through objects that the file can see.So on your Page make a property:
property int horizSize
Then in parent set that size:
horizSize: 10
Or use a property from another higher up object in the same page:
horizSize: pagemaster.horizSize
Then the pagemaster object may get set by another place it was included.
-
I don't think that you understood my question.
I didn't use custom properties. I can see that they exist, based on posts like in this topic, and this one below:
https://stackoverflow.com/questions/35061494/adding-custom-properties-to-qml-typeIf I ever needed a custom property, sure, it seems just like a variable to me, but assuming that this is a "property" of an object, then it would be accessed just like other properties of objects...
My point is. I don't need a custom property, I want to read from a property of an object outside of the currently selected file.
Whether it is parent, or not. I can access it as parent.(property name) (if the accessing happens in the same file and the accessing object is a child), or (id of object).(property name) (and in theory this should work across all files).I have an object with default properties, and I assign value to those properties.
Two of them are height and width properties, and I can read from Screen properties, and assign value of those to the properties of ApplicationWindow.Then I want to read properties of ApplicationWindow in another file, but that file has no access to objects inside main.qml or (supposedly) page1 or page3 (assuming that im inside page 2 file).
I selected the ID approach, as it is in my opinion better looking and easier to use. The problem is that the ID is not shared across different QML files it seems.
Is there any method for bypassing this issue then, or perhaps you can do that using a custom property, and this type of property is "magically" shared across all files?
It could be that a property is private to non-children (aka objects of other classes nested outside of main file), so then the transfer of data would happen by another variable I guess?
Is this what you wanted to point at?
If so, then thank you.
-
ApplicationWindow { id: mainWindow //Wide screen support //Screen.desktopAvailableWidth / 4 //Screen.desktopAvailableHeight / 6 //The below is monitor cross-compatible (phone, PC, laptop) property int globalWidth: Screen.width / 2 property int globalHeight: Screen.height / 3 width: globalWidth height: globalHeight visible: true title: qsTr("Redacted") //setWindowIcon(QIcon(":/path/to/icon.png"));
Page { id: localPage2 width: Screen.width / 2 height: Screen.height / 3 Rectangle { id: rectangle x: (localPage2.width / 2) - (width / 2) y: (localPage2.height / 4) - (height / 2) width: localPage2.width / 3 height: localPage2.height / 6 color: "#ffffff" border.color: "#a45c5c" border.width: 2 TextInput { id: textInput x: 0 y: 0 width: localPage2.width / 3 height: localPage2.height / 6 text: qsTr("Redacted") font.pixelSize: 12 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter font.weight: Font.Normal focus: true } } }
Then
Page { id: localPage2 width: globalWidth height: globalHeight Rectangle { id: rectangle x: (localPage2.width / 2) - (width / 2) y: (localPage2.height / 4) - (height / 2) width: localPage2.width / 3 height: localPage2.height / 6 color: "#ffffff" border.color: "#a45c5c" border.width: 2 TextInput { id: textInput x: 0 y: 0 width: localPage2.width / 3 height: localPage2.height / 6 text: qsTr("Redacted") font.pixelSize: 12 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter font.weight: Font.Normal focus: true } } }
Seems to be working, but I was sure that a moment ago it was broken.
(30 seconds later). It is.id: localPage2 width: ApplicationWindow.globalWidth height: ApplicationWindow.globalHeight
Page { id: localPage2 width: mainWindow.globalWidth height: mainWindow.globalHeight
same
Offtopic:
@sierdzio said in [SOLVED]Accessing variables of other QML files:id is "protected" in that sense - ids are only valid within QML files. If you import a file, id info is not accessible outside. That is why you can and should use QML properties.
restricted usability, but still usable
@sierdzio said in [SOLVED]Accessing variables of other QML files:
Try what I wrote before.
As I've noticed, properties that are to be exposed to other QML files need to be defined in top-level item in the source file. So in your code, the group property should be defined in "main" Item, not in "variable" item inside File.qml.
doesn't work in my case
-
@Matthew0x said in Dynamic size QML Page unable to render:
I want to read from a property of an object outside of the currently selected file.
Even if it was possible to global scope a QML object it would be bad design. It would create dependencies between objects and lead to dependency hell. It would also make for un-reusable code.
The way I understand QML is it is a declarative language. It creates objects and gives them the data needed in the instance of the object, not in the definition. This allows data to flow downward to various objects via the property mechanism.
An instance of this is ListView. Its delegates get temporary custom properties assigned in them when created. The delegates use these properties. If you use the same properties in different models then your delegates can be generic and the ListView can be generic. This leads to potentially a lot less code.
-
@fcarney I literally had the issue of accessing a class property (member variable) from another class, that was in fact invoked inside the either App class or App function (not sure which it is, possibly just a function?, but what would be its "properties", global variables? function variables?)
It turned out that I could do that in objects declared elsewhere, in ui.qml but not in the main.qml file for some reason (so that is, the AppWindow class/function).
I didn't dig further into this, as I got stuck on a bug related to rendering of SpinBox, that looks broken in my interface.
"Even if it was possible to global scope a QML object it would be bad design."
I believe it is (possible, as I supposedly managed to do that, although I can't judge whether it's class anchored in another class, or object initialization inside function... possibly the latter), and I can't see anything bad about it. This is how OOP works...Classes have got accessors and setters or member functions/friendly functions. How else can I build an interface with dynamically changed data inside (labels, values...) if I wouldn't be able to access Page 1 from Page 99, or change the looks of main window basing on "Settings" tab somewhere else?
This is how the entire OS is written. As to delegates, I have little experience with them. As far I am concerned, they're just function pointer, but this is the "C#" nomenclature, that I personally hate.
PS: It would possibly be much, much, much easier for me to write code in clean C++, but I have no knowledge of any decently looking frameworks with cross-compatibility that would work fine in C language.
I don't like the C++ style in Qt Designer, so I am using QML. I hate arrows for example...
-
@Matthew0x said in Dynamic size QML Page unable to render:
This is how OOP works...
If you are writing c++ and global scoping your instances you are headed for trouble. You should be using RAII. QML is a declarative language. Where the data flows down to from the instance of one object to another. Separate QML files don't know about each other because they are the declaration of the object type. The instance is the object created in another QML file. Where the Window instance is created in C++.
main.qml:
Window { id: window Item{ id: item } }
This is the declaration. It is NOT the instance. The instance for Window is created from C++ (usually, unless you have a sub window). The Item is also declared here. But once the Window is instanced so is the Item. However, this window could be instanced again either from C++ or another QML file. Which one is the correct "window" at this point? That means this QML file can only be used once if you could access "window" anywhere. This limits how you can use the Window and limits code reuse. What if you decide you want to open multiple documents with the same Window?
Applying RAII to QML is how you provide data.
main.qml:
Window { id: window CustomItem{ id: item // this data is provided when instanced, and updated as they change allowing your subitem to be dynamic objectINeedFromParent: window.screen width: window.width * 0.5 height: window.height * 0.5 } }
customItem.qml:
Item { property var objectINeedFromParent }
See how the data flows down? This is similar to RAII as used in C++. You are presenting data to the Item when instanced. Not inside its definition.
If you really need some global data for an object that doesn't get deleted then use a C++ object and define a context property. But that is for data you need everywhere. It can lead to coupling issues making QML objects less reusuable.