How to put multiple singletons in one qmldir file? - qt

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.

Related

How to create a "creatable" qml singleton?

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

Unable to assign [undefined] to QColor when including QtObject as styling file

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!

ListView doesn't update when its model data changes

I have a QList<QObject*> that is read from within a ListView module into a model. At first the QList is an empty object. I want the indexBackup to be updated when I assign a new list to the QList object.
import QtQuick 2.5
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.2
import QtQuick.Controls.Styles 1.0
ListView {
id: layersListView
model: settingsList //QList<QObject*> object
int indexBackup: 0
onModelChanged: {
if(indexBackup && indexBackup < model.length)
{
indexBackup = model.length
}
else
{
indexBackup = - 1
}
}
}
For everybody with similar problem, the answer can be found here.

declaring string in .qml files

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.

QML - How to insert an Item at any position in StackLayout?

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.

Resources