Using Loader along with StackLayout
-
Hi all -
My main display has a TabBar and a main display area. The customer wants a screen that will cover the main display area. I've mocked up an attempt at this as follows:
ApplicationWindow { menuBar: Maintabbar { id: navBar } ColumnLayout { Loader { id: mainLoader } Maincontent { // Maincontent is a StackLayout id: mainContent currentIndex: navBar.tabIndex } ... MouseArea { onClicked: { drawer.close() if (mainLoader.status === Loader.Null) { mainLoader.source = "qrc:/newscreen.qml" } else { mainLoader.source = "" } } } } }The new screen appears just fine, but on the second click, the original display isn't restored. Anyone have suggestions on how to make this work (or a better way to do the same thing)?
Thanks...
-
If you use the stackview instead, it essentially already is a loader. No need for two and no need to handle special cases.
So, what I think I read from your description is that during startup you want to show special screen and later you want to just show the main screens. Right?
You can do that with a StackView and the
initialItemproperty. Then when you want to remove that one and show your normal stuff you just callreplace().Example here.
-
If you use the stackview instead, it essentially already is a loader. No need for two and no need to handle special cases.
So, what I think I read from your description is that during startup you want to show special screen and later you want to just show the main screens. Right?
You can do that with a StackView and the
initialItemproperty. Then when you want to remove that one and show your normal stuff you just callreplace().Example here.
@TomZ said in Using Loader along with StackLayout:
So, what I think I read from your description is that during startup you want to show special screen and later you want to just show the main screens. Right?
That wasn't my intention for this topic, though it is something I'm going to have to deal with eventually (I'm looking into using an mp4 for my splash screen). The "normal" operation of the app is to populate the main display based on the tab selection. (This is currently handled through a StackLayout.)
At some point, though, I'll need to enter a text input screen that isn't represented in the StackLayout (because there's no tab for it). I was hoping to use the Loader for this. Perhaps a Popup would be more appropriate?
-
@TomZ said in Using Loader along with StackLayout:
So, what I think I read from your description is that during startup you want to show special screen and later you want to just show the main screens. Right?
That wasn't my intention for this topic, though it is something I'm going to have to deal with eventually (I'm looking into using an mp4 for my splash screen). The "normal" operation of the app is to populate the main display based on the tab selection. (This is currently handled through a StackLayout.)
At some point, though, I'll need to enter a text input screen that isn't represented in the StackLayout (because there's no tab for it). I was hoping to use the Loader for this. Perhaps a Popup would be more appropriate?
@mzimmers said in Using Loader along with StackLayout:
The "normal" operation of the app is to populate the main display based on the tab selection. (This is currently handled through a StackLayout.)
Personally not a fan of the stack layout for tabs. They complicate stuff. Each tab should have the same dimensions which basically just means you should show one and hide the others. Trivial code;
Item { default property alias content: stack.children property int currentIndex: 0 onCurrentIndexChanged: setOpacities() Component.onCompleted: setOpacities() function setOpacities() { for (let i = 0; i < stack.children.length; ++i) { let on = i === currentIndex; let child = stack.children[i]; child.visible = on; } } Item { id: stack width: root.width anchors.top: header.bottom; anchors.bottom: tabbar.top } -
@mzimmers said in Using Loader along with StackLayout:
The "normal" operation of the app is to populate the main display based on the tab selection. (This is currently handled through a StackLayout.)
Personally not a fan of the stack layout for tabs. They complicate stuff. Each tab should have the same dimensions which basically just means you should show one and hide the others. Trivial code;
Item { default property alias content: stack.children property int currentIndex: 0 onCurrentIndexChanged: setOpacities() Component.onCompleted: setOpacities() function setOpacities() { for (let i = 0; i < stack.children.length; ++i) { let on = i === currentIndex; let child = stack.children[i]; child.visible = on; } } Item { id: stack width: root.width anchors.top: header.bottom; anchors.bottom: tabbar.top }@TomZ thanks for the suggestion. I've turned your snippet into a working module, for anyone who might be interested:
import QtQuick import QtQuick.Controls ApplicationWindow { id: mainWindow visible: true width: 800 height: 480 function setVisibility() { for (let i = 0; i < stack.children.length; ++i) { let child = stack.children[i]; let isVisible = (i === stack.currentIndex); child.visible = isVisible; } } menuBar: TabBar { id: tabBar TabButton {text: "1"; onPressed: stack.currentIndex = 0} TabButton {text: "2"; onPressed: stack.currentIndex = 1} TabButton {text: "3"; onPressed: stack.currentIndex = 2} TabButton {text: "pop up"; onPressed: stack.currentIndex = 3} } Item { id: stack property int currentIndex: 0 onCurrentIndexChanged: setVisibility() Component.onCompleted: setVisibility() Rectangle {height: 100; width: 100; color: 'red'} Rectangle {height: 100; width: 100; color: 'green'} Rectangle {height: 100; width: 100; color: 'blue'} Popup { height: mainWindow.height * 0.8 width: mainWindow.width * 0.8 anchors.centerIn: Overlay.overlay background: Rectangle { color: 'yellow' } visible: stack.currentIndex === 3 } } }It appears that since I'm not using a StackLayout, I have to manage setting the currentIndex property myself (not a big deal). Seems like a reasonable alternative.
-
@TomZ thanks for the suggestion. I've turned your snippet into a working module, for anyone who might be interested:
import QtQuick import QtQuick.Controls ApplicationWindow { id: mainWindow visible: true width: 800 height: 480 function setVisibility() { for (let i = 0; i < stack.children.length; ++i) { let child = stack.children[i]; let isVisible = (i === stack.currentIndex); child.visible = isVisible; } } menuBar: TabBar { id: tabBar TabButton {text: "1"; onPressed: stack.currentIndex = 0} TabButton {text: "2"; onPressed: stack.currentIndex = 1} TabButton {text: "3"; onPressed: stack.currentIndex = 2} TabButton {text: "pop up"; onPressed: stack.currentIndex = 3} } Item { id: stack property int currentIndex: 0 onCurrentIndexChanged: setVisibility() Component.onCompleted: setVisibility() Rectangle {height: 100; width: 100; color: 'red'} Rectangle {height: 100; width: 100; color: 'green'} Rectangle {height: 100; width: 100; color: 'blue'} Popup { height: mainWindow.height * 0.8 width: mainWindow.width * 0.8 anchors.centerIn: Overlay.overlay background: Rectangle { color: 'yellow' } visible: stack.currentIndex === 3 } } }It appears that since I'm not using a StackLayout, I have to manage setting the currentIndex property myself (not a big deal). Seems like a reasonable alternative.
Just to close the loop on this one, I ended up not going with a StackLayout for this. I added a signal to the screen from which I wanted to induce the Popup:
Roundlist.qml
Rectangle { signal doClick(int index) ListView {} Component { Rectangle { MouseArea { enabled: true anchors.fill: parent onClicked: { doClick(index) } } } } }And then simply:
Roundlist { id: name width: newZone.width model: zoneNameModel onDoClick: { textInputPopup.open() // textInputPopup is a Popup } }Much easier than my original idea.
-
M mzimmers has marked this topic as solved on