Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Using Loader along with StackLayout

Using Loader along with StackLayout

Scheduled Pinned Locked Moved Solved QML and Qt Quick
6 Posts 2 Posters 834 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #1

    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...

    1 Reply Last reply
    0
    • TomZT Offline
      TomZT Offline
      TomZ
      wrote on last edited by
      #2

      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 initialItem property. Then when you want to remove that one and show your normal stuff you just call replace().

      Example here.

      mzimmersM 1 Reply Last reply
      0
      • TomZT TomZ

        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 initialItem property. Then when you want to remove that one and show your normal stuff you just call replace().

        Example here.

        mzimmersM Offline
        mzimmersM Offline
        mzimmers
        wrote on last edited by
        #3

        @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?

        TomZT 1 Reply Last reply
        0
        • mzimmersM mzimmers

          @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?

          TomZT Offline
          TomZT Offline
          TomZ
          wrote on last edited by
          #4

          @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
              }
          mzimmersM 1 Reply Last reply
          1
          • TomZT TomZ

            @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
                }
            mzimmersM Offline
            mzimmersM Offline
            mzimmers
            wrote on last edited by
            #5

            @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.

            mzimmersM 1 Reply Last reply
            0
            • mzimmersM mzimmers

              @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.

              mzimmersM Offline
              mzimmersM Offline
              mzimmers
              wrote on last edited by
              #6

              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.

              1 Reply Last reply
              0
              • mzimmersM mzimmers has marked this topic as solved on

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved