I have 2 QML Silica Pages, Main.qml and Icon.qml.
Main.qml has this distribution:
import QtQuick 2.0
import Sailfish.Silica 1.0
import io.thp.pyotherside 1.3
Page {
SilicaFlickable {
id: mainList
Button {
text: "Stack the next page"
onClicked: { // Stack de Icon Page
pageStack.push(Qt.resolvedUrl("Icon.qml"))
}
}
function reload(){ }
Python {
id: py
Component.onCompleted: { mainList.reload() }
}
}
}
And I want to call the function reload() since Icon:
import QtQuick 2.0
import Sailfish.Silica 1.0
import io.thp.pyotherside 1.3
Page {
id: iconEditor
Button {
onClicked: {
pageStack.pop()
pageStack.completeAnimation()
pageStack.currentPage.mainList.reload() // Fail
}
}
}
The Main.qml Page is stacked in the principal QML file like this:
import QtQuick 2.0
import Sailfish.Silica 1.0
import io.thp.pyotherside 1.3
ApplicationWindow {
id: root
Python {
Component.onCompleted: {
pageStack.push(Qt.resolvedUrl("Main.qml"))
}
}
}
How can I call the function on the previous page of the stack?
The "id" have as scope only the .qml where it was defined and cannot (or should be used outside of that scope). If you want to expose objects or variables then you must do it by creating a property in the toplevel of the file.
In this case a solution is to use an alias property:
import QtQuick 2.0
import Sailfish.Silica 1.0
import io.thp.pyotherside 1.3
Page {
property alias mainList: mainList
SilicaFlickable {
id: mainList
// ...
Related
my code
AppDelegate.js for global variables
.pragma library
var appDelegate= {}
MyApp.js
Qt.include("AppDelegate.js")
function AppDelegate(){
}
AppDelegate.prototype.doSomething=function() {
console.log("vvvvvvvvvvvvv")
}
AppDelegate.prototype.doSomething1=function() {
console.log("AAAAAAAAAAAAAA")
}
//-------------------------------------------------------
function initApp(){
appDelegate=new AppDelegate()
appDelegate.doSomething()
appDelegate.doSomething1()
}
MyApp.qml
import QtQuick 2.2
import QtQuick.Controls 1.2
import "MyApp.js" as MyApp
ApplicationWindow {
visible: true
title: "System Dialogs Gallery"
width: 580
height: 480
TabView {
anchors.fill: parent
anchors.margins: 8
Tab {
id: controlPage
title: "File"
FileDialogs { }
}
}
Component.onCompleted: {
MyApp.initApp()
}
}
it works well and output is
qml: vvvvvvvvvvvvv
qml: AAAAAAAAAAAAAA
but if I call from other .js .qml file
ColorDialogs.js
Qt.include("AppDelegate.js")
function doit(){
appDelegate.doSomething1()
}
ColorDialogs.qml
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.1
import "ColorDialogs.js" as ColorDialogs
Item {
Component.onCompleted: {
ColorDialogs.doit()
}
}
it reports error:
ColorDialogs.js: : TypeError: Property 'doSomething1' of object [object Object] is not a function
Your comment welcome
----------------------------updated
Following is the sample Button QML code that I found in google:
Button {
id: myButton
text: "btnTxt";
function buttonClick()
{
console.log("Button "+ myButton.text +" is clicked!")
}
MouseArea {
id: myMouseId
anchors.fill: parent
onClicked:
{
myButton.buttonClick();
}
}
style: ButtonStyle {
background:
Rectangle {
color: myMouseId.pressed ? "#336699" : "#0099FF";
radius: 1;
}
}
}
And I am using the following imports:
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.4
But, Qt threw the error:
Invalid property assignment: "pressed" is a read-only property
Also, is there an complete example for this basic type? I couldn't find in the doc how to address the above condition.
I'm trying to put the business logic in Main.qml and the UI in MainForm.ui.qml but I can't connect both by widget id.
MainForm.ui.qml:
import QtQuick 2.8
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
Page {
id: page
header: TabBar { ... }
StackLayout {
id: stack
Pane {
Flow {
TextField {
id: theText
}
property alias sendBtn: sendBtn
Button {
id: sendBtn
}
}
}
}
}
Main.qml:
import QtQuick 2.8
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MainForm {
anchors.fill: parent
sendBtn {
onClicked: backend.sendTextToServer( theText.text )
}
}
}
Qt Creator says : Invalid property name "sendBtn" (M16)
Running failed with the following messages:
QQmlApplicationEngine failed to load component
qrc:/Main.qml:12 Cannot assign to non-existent property "sendBtn"
when you put property alias sendBtn: sendBtn inside Pane is interpreted as being a Pane property so you can not access it that way, it is correct to place it in the context of Page.
import QtQuick 2.8
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
Page {
id: page
property alias sendBtn: sendBtn
property alias theText: theText
header: TabBar { ... }
StackLayout {
id: stack
Pane {
Flow {
TextField {
id: theText
}
Button {
id: sendBtn
}
}
}
}
}
I have a larger QML project that I'm trying to refactor so that some related components are in their own file. In my simplified example, what is part of ThingManager.qml was previously simply included in the main.qml file. Prior to refactoring, the scope of ids, a, b, and c were visible to page.qml since they were defined in the main file. As I tried to abstract these into a ThingManager component to reduce clutter in my main.qml, page.qml was no longer able to reference those with the familar scoping error:
page.qml:9: ReferenceError: a is not defined
Given that I am loading pages similar to page.qml and want to execute methods within these components stored in another file, what is the recommended way to refactor something like this example such that page.qml can access methods in these components without them being defined in main.qml? Or is that simply not possible to do?
main.qml:
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQml 2.2
ApplicationWindow {
id: window
ThingManager { }
Loader {
id: page_loader
}
Component.onCompleted: {
page_loader.setSource("page.qml")
}
}
ThingManager.qml:
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
Item {
Column {
Button {
id: a
text: "A"
}
Button {
id: b
text: "B"
}
Button {
id: c
text: "C"
}
}
}
page.qml:
import QtQuick 2.7
import QtQuick.Controls 2.1
Page {
id: page
Component.onCompleted: {
console.log("Execute A's method")
a.toggle()
}
}
You should add an id to ThingManager and define a as an alias property in ThingManager.qml as follows:
main.qml:
...
ThingManager {id: manager }
...
ThingManager.qml:
Item {
property alias a: a // makes 'a' available outside this file
property alias b: b
property alias c: c
...
}
page.qml:
...
manager.a.toggle ()
...
I want to use some qml file(main.qml) but before that I need to get some authentication info from user(login, pass). So I want to do this in the second window(login.qml). I saw Qt.createComponent for opening second qml file, but I can't get any information from this type of window.
So how can I use some information from the second window in the first window?
Or how can I dynamically load these items(main.qml, login.qml) in the parent qml file?
So how can I use some information from the second window in the first
window?
This is just one way of doing it:
main.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
ApplicationWindow {
width: 400
height: 400
visible: true
ColumnLayout {
id: logItems
height: 200
Button {
id: loginButton
onClicked: loginForm.visible = true
text: "Log in"
}
Login {
anchors.top: loginButton.bottom
id: loginForm
visible: false
onLoginInfo: {
logInfo.text = "User:" + user + " password: " + password
}
}
}
Text {
id: logInfo
anchors.top : logItems.bottom
}
}
Login.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
Item {
signal loginInfo(string user, string password)
ColumnLayout {
RowLayout {
TextField {
id: user
}
TextField {
id: password
}
}
Button {
text: "Submit"
onClicked: loginInfo(user.text, password.text)
}
}
}
How can I dynamically load QML items from separate files/resources in
another QML file?
Qt.CreateComponent allows you to use JavaScript to dynamically create and use QML code from other files.