I am trying to make a varaibles file in qml which declares several strings to be used by other qml files. for example: this would be Variables.qml
import QtQuick 2.0
Item {
property var mystring: qsTr("hello world")
}
and I want to reference it in another file tab1.ui.qml
import QtQuick 2.4
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3
import "."
Item {
Rectangle {
id: rectangle
color: "#3e1edd"
anchors.fill: parent
Text {
id: text6
anchors.fill: parent
font.pixelSize: 12
text: Variables.mystring
visible: true
}
}
}
this gives an error: Unable to assign [undefined] to QString
please tell me if there is a better way to manage variables. I want them to be global so they can be used in multiple frames. Thanks
You must use a singleton, for it you must create a folder that contains the .qml with "pragma Singleton" at the top and a qmldir that indicate the files:
Global
├── qmldir
└── Variables.qml
qmldir
singleton Variables 1.0 Variables.qml
Variables.qml
pragma Singleton
import QtQuick 2.0
QtObject {
property var mystring1: qsTr("hello world1")
property var mystring2: qsTr("hello world2")
}
Then you must import and use it in the following way:
// others imports
import "Global"
// ...
Text{
// ...
text: Variables.mystring1
}
In this link you will find an example.
Related
I have a use case where I need to instantiate a singleton in qml (for property bindings).
i.e:
File: main.qml
Item{
MainQuery{id: mainquery
graphql: `query MainQuery{...}`
}
Text{
text: mainquery.data
}
}
This other file should use the query defined in main.qml
File: otherfile.qml
Item{
import MyLib 1.0 as Gql
Text{
text: Gql.MainQuery.data
}
}
However if you use QML_SINGLETON you can't initialize it in QML
and in order to bind to the graphql property above you would have to use
Connection.
Is there a better solution?
Note:
The object should be a singleton in CPP / Python side as well.
currently it is implemented in python like this:
class QSingleton(type(QObject)): # type: ignore
def __init__(cls, name, bases, dict):
super().__init__(name, bases, dict)
cls.instance = None
def __call__(cls, *args, **kw):
if cls.instance is None:
cls.instance = super().__call__(*args, **kw)
return cls.instance
class BaseQuery(QObjcet, QSingleton):
...
#QmlElement
class MainQuery(BaseQuery):
...
And gives this nice error when the qml engine tries to initiate the type:
QEventLoop: Cannot be used without QApplication
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
(I do have an eventloop running)
Whether the underlying Python object is or is not a singleton it doesn't matter. We can always declare a singleton wrapper in QML by defining a qmldir and using pragma Singleton in our source file. To demonstrate this approach, I wrap TextMetrics in my singleton object and expose TextMetrics properties as properties of my singleton so that I can use property binding with singleton syntax:
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
Frame {
anchors.centerIn: parent
ColumnLayout {
TextField {
text: "Hello"
onTextChanged: MyWrapper.tmText = text
}
Text {
text: MyWrapper.tmWidth
}
}
}
}
// qmldir
module ExampleWrapper
singleton MyWrapper 1.0 MyWrapper.qml
// MyWrapper.qml
pragma Singleton
import QtQuick
import QtQuick.Controls
Item {
property alias tmText: tm.text
property alias tmWidth: tm.width
TextMetrics {
id: tm
text: "Hello"
}
}
You can Try it Online!
References:
https://doc.qt.io/qt-6/qtqml-modules-qmldir.html
I am trying to add set of custom properties to be included by several labels on my QML. The idea is to make a style, but I keep getting these errors:
qrc:/TestPage.qml:18:9: Unable to assign [undefined] to QColor
qrc:/TestPage.qml:17:9: Unable to assign [undefined] to double
qrc:/TestPage.qml:16:9: Unable to assign [undefined] to QString
I was following the thread below but did not work for me.
Unable to assign [undefined] to QColor
Here is my label:
import "Theme"
Label
{
font.family: Theme.tfont
font.pointSize: Theme.tpointSize
color: Theme.tcolor
text: "text"
}
and here is my Theme.qml file:
pragma Singleton
import QtQuick
QtObject
{
readonly property string tfont: {return "Calibri"}
readonly property real tpointSize: {return 28}
readonly property string tcolor: {return "black"}
}
any ideas why it won't resolve the property?
Check that example it uses a Style.qml to define a global theme. As Stephen Quan already said you should create a qmldir to define the singleton.
The important part here is to also include the qmldir and the Theme.qml in your CMakeLists.txt or pro.
CMakeLists.txt
...
qt_add_qml_module(appuntitled
URI untitled
VERSION 1.0
QML_FILES
main.qml
qmldir
Theme.qml
)
...
qmldir
singleton Theme 1.0 Theme.qml
Theme.qml
pragma Singleton
import QtQuick
QtObject {
readonly property string tfont: "Calibri"
readonly property real tpointSize: 28
readonly property string tcolor: "black"
}
main.qml
import QtQuick
import QtQuick.Controls
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Label {
font.family: Theme.tfont
font.pointSize: Theme.tpointSize
color: Theme.tcolor
text: "text"
}
}
I made the following changes to your app:
Declare qmldir
Don't need import "Theme"
Refactor AppLabel
Don't use return when declaring properties declaratively
import QtQuick
import QtQuick.Controls
Page {
AppLabel { text: "text" }
}
//AppLabel.qml
import QtQuick
import QtQuick.Controls
Label {
font.family: Theme.tfont
font.pointSize: Theme.tpointSize
color: Theme.tcolor
}
//qmldir
singleton Theme 1.0 Theme.qml
//Theme.qml
pragma Singleton
import QtQuick
QtObject
{
readonly property string tfont: "Calibri"
readonly property real tpointSize: 28
readonly property string tcolor: "black"
}
You can Try it Online!
I want to use multiple singletons in one qmldir file but it doesn't seem to work, I don't have an error but the program doesn't launch.
qmldir:
singleton File1 1.0 File.qml
singleton File2 1.0 File2.qml
main:
import QtQuick 2.7
import QtQuick.Controls 2.1
Window {
visible: true
width: 640
height: 480
title: qstr("hello world!")
Button {
onCliked: File2.test();
}
}
File2.qml:
pragma Singleton
import QtQuick 2.7
Item {
signal test;
onTest: console.log("File2 received signal");
}
File1.qml:
pragma Singleton
import QtQuick 2.7
Item {
signal test;
onTest: console.log("File1 received signal");
}
The code works if I delete the second line in qmldir, but then File2 will be undefined.
If your qmldir file is exactly as you have written:
Singleton File1 1.0 File.qml
Singleton File2 1.0 File2.qml
The error might reside within that, as the keyword is singleton, not Singleton.
Try that:
singleton File1 1.0 File.qml
singleton File2 1.0 File2.qml
But that error should not fail silently. There should be some errors:
[main.qml] a component declaration requires two or three arguments, but 4 were provided
[qmldir] a component declaration requires two or three arguments, but 4 were provided
main.qml:
import QtQuick 2.7
import QtQuick.Controls 2.0
import '.'
ApplicationWindow {
id: window
width: 800
height: 600
visible: true
Row {
spacing: 3
Button {
text: 'single1'
onClicked: Single.sig()
}
Button {
text: 'signle2'
onClicked: Single2.sig()
}
}
}
singleton.qml
pragma Singleton
import QtQuick 2.0
QtObject {
signal sig
onSig: console.log('Singleton1 Received')
}
singleton2.qml
pragma Singleton
import QtQuick 2.0
QtObject {
signal sig
onSig: console.log('Singelton2 Received')
}
qmldir
singleton Single 1.0 singleton.qml
singleton Single2 1.0 singleton2.qml
Works like a charm.
I need to add a component at a particular position in stack layout and I am not getting how to insert, following is the code.
import QtQuick 2.6
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
Component{
id:comp
Rectangle{
id:rect
anchors.fill:parent
}
}
StackLayout
{
id:stack
anchors.fill:parent
currentIndex:index //spin box will update this property
}
Button
{
id:insert
onClicked:
{
var res = comp.createObject(stack) // Should insert a rect at a position not at the end
}
}
Got the answer and also may be duplicate of:
https://stackoverflow.com/a/43225476/6336374
I used insert(index,item) of ObjectModel
Thanks to #derM it helped a lot.
In Qt 5.3 I've been using the Loader QML element for loading screens, loading the view from a QML file in the background. Now I'm trying to load a string of QML dynamically. Qt.createQmlObject enables me to do so, but I can't seem to get the Loader element to play along.
Seems like Loader only takes a URL (QUrl) or component (QQmlComponent), but Qt.createQmlObject creates an object (QObject).
I'm new to QML, but from my understanding components are reusable elements, similar to classes, and objects are the instances of those classes. I thus can't seem to wrap my head around why Loader wouldn't work with objects.
How can I show a loading screen while (asynchronously) parsing and initializing a string of QML?
Example QML code:
Item {
Rectangle {id: content}
Loader {id: loader}
Component.onCompleted: {
var obj = Qt.createQmlObject('import QtQuick 2.3; Rectangle {}', content);
loader.source = obj; // Throws error.
}
}
It's not possible using the current API. As Loader's documentation says, it loads objects via a URL that points to a QML file or a Component:
import QtQuick 2.0
Item {
Rectangle {
id: content
anchors.fill: parent
color: "grey"
Loader {
id: loader
sourceComponent: myComponent
anchors.fill: parent
anchors.margins: 40
}
}
property Component myComponent: Qt.createComponent("MyComponent.qml", Component.Asynchronous)
}
MyComponent.qml:
import QtQuick 2.2
Rectangle {
color: "red"
}