How can I load a external QML file in Qt Quick? - qt

Ok like if I'm trying to make something like a menu for a simple game. How can I make it so that when the start button is clicked it loads a different QML file?

You can use Qt.createComponent() or Loader. For example:
import QtQuick 1.0
Item {
MyButton {
onClicked: loader.source = "MyGameFile.qml"
}
Loader {
id: loader
anchors.fill: parent
}
}

Related

Change Loader source and update view

I have an application in which i am loading some resources inside a main file with a Loader object:
main.qml:
ApplicationWindow {
property string pageSource: pageLoader.source
...
Loader {
id: pageLoader
source: "page1.qml"
}
}
In page1.qml i have a layout that wraps some buttons and text fields. Loading this page in pageLoader works fine. As you can see i have a foo Button that should switch the source of the Loader to page2.qml, but for some reason it's not working.
page1.qml:
Item {
ColumnLayout {
TexField {...}
TexField {...}
Button {
id: foo
onClicked: {
pageSource = "page2.qml"
}
}
}
}
By checking some console logs i was able to know that i am actually changing the source of the loader, but the view is not updating as expected and all controls from page1.qml is not replaced by page2.qml. This second page has a ListView. Toggling active property of Loader doesn't work either. Can anyone please shed a light?

Qt - How to connect signal from loader item, if loader source changes dynamically

I have an application which needs the screen to be switched between multiple available screens. I am checking if this is possible with loader in qml.
The issue i am facing is connecting signals from loaded item.
I use an application example in qt documentation and found CreateConnection in application qml cannot have if condition.
I also tried to make it signal slot connection in a function and call in on source change of loader, but that too did not work.
Application.qml
import QtQuick 2.0
Item {
width: 100; height: 100
Loader {
id: myLoader
source: "MyItem.qml"
}
Connections {
target: myLoader.item
// here i tried using if (myLoader.item == "qrc:MyItemOne.qml") , but can't use if
onChangeToSecond: {
myLoader.source = "MyItemTwo.qml"
}
onChangeToFirst: {
myLoader.source = "MyItemOne.qml"
}
}
}
MyItemOne.qml
import QtQuick 2.0
Rectangle {
id: myItem
signal changeToSecond()
width: 100; height: 100
MouseArea {
anchors.fill: parent
onClicked: myItem.changeToSecond()
}
}
MyItemTwo.qml
import QtQuick 2.0
Rectangle {
id: myItem
signal changeToFirst()
width: 100; height: 100
MouseArea {
anchors.fill: parent
onClicked: myItem.changeToFirst()
}
}
Someone knows any way to use loader for this, or loader should not be used for this?
Your code works fine if I use MyItemOne.qml as the initial value for the myLoader.source (Qt5.6.0). However, it will print out a warning:
QML Connections: Cannot assign to non-existent property "onChangeToFirst"
which happens because MyItemOne does not define the changeToFirst signal. The ignoreUnknownSignals property of Connections element can be used to suppress the warning, or both screens should define the same set of signals.
Loader can be used if it does not matter that the previous view is always fully unloaded when switching.

Using a Loader for a string of QML

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"
}

How to set a QML plugin as the source for a Loader

I've created a QML plugin and I can use it as :
import "MyElement" 1.0
Rectangle{
width:500;height:500;
MyElem{
}
}
MyElem is the plugin.
Now I'm wondering how I can use this plugin as a source for a Loader element? The source of loader expects a string but here we have a component.
You can use it for the loader like this:
import "MyElement" 1.0
Component {
id: myElement
MyElem{
}
}
Loader { sourceComponent: myElement}

Navigating and addressing QMLComponents

I am working on a desktop application the uses a QML GUI with a lot of QML Components.
These are parts of the hierarchy:
main -> toolbar -> searchbar -> editfield
and
main -> resultlist -> header -> button1
I could not find a way to access the text contents of editfield in a signal handler for button1. Is it possible to do that in QML or Javascript?
I know I can access the element in the C++ part by using the objectName property.
Due to QML uses dynamic scoping (→ Doc), child elements can access the properties of all ancestors
and it doesn't matter if they are in different files.
So you could add an editFieldText property to main and bind the
text property of editfield to it. Then you can access editFieldText
from everywhere:
//=== main.qml ===
import QtQuick 1.0
Rectangle {
id: main
property string editFieldText
Toolbar {
// [...]
}
Resultlist {
// [...]
}
}
//=== EditField.qml ===
import QtQuick 1.0
TextInput {
// bind text property to main.editFieldText
Binding {
target: main;
property: "editFieldText";
value: text
}
}
//=== Header.qml ===
import QtQuick 1.0
Rectangle {
Button {
onClick: {
console.log(main.editFieldText);
// or simply
console.log(editFieldText);
}
}
}
You can use alias properties to have the editfield.text as a property of main. This property should be accessible from button1.

Resources