Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

qml How to use loader within tabview

Tags:

android

qt

qml

I can not find a way to use a loader to fill a tab within a tabview. The loader works fine when it is outside of the TabView (ie if I remove the multi line comment characters at the top of mainTrial.qml and the Loader plus Connections are at the top. But if I move the Loader in line as a child of a tab, I get an error "Cannot assign multiple values to a singular property. Neither can I address the Loader that is outside of TabView using menuLoader.source or column1.menuLoader.source or other variants. Here is the main file. (the other two files that define the signals are included so that you can see that the signals work). What am I doing wrong?

Edit: (Good ole law of permutations and combinations) I discovered that if I make the Connections declaration, a child of the Loader that is on the tab, the problem goes away. I will have but one "value" assigned on the tab - that being the Loader and now I can load a qml item per tab.

//mainTrial

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1 


Item {
    id: trial
    width: 360
    height: 360
    ColumnLayout {
        id: column1
        spacing:150
        Item {Layout.fillHeight: true}
        TabView {
            id: tabPages
            Tab {
                id: welcomePage
                title: "Welcome"
                // /*
                Loader{
                    id: menuLoader
                    source: "mainTrial1.qml"
                    anchors.top: parent.top
                    Connections {
                        id: menuConnection
                        ignoreUnknownSignals: true
                        target: menuLoader.item
                        onMainTrial3: {
                            menuLoader.source = "mainTrial3.qml"
                            console.log("originated from " + origin)
                        }
                        onMainTrial1: {
                            menuLoader.source = "mainTrial1.qml"
                            console.log("originated from " + origin)
                        }
                    }
                }        
            }
            Tab {
                id: statusPage
                title: "Status"
            }
        }
    }
}

// mainTrial1 (with one signal definition)

This file defines one of the signals used to load the next qml object. I included it here so that you can see that the signal works).

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1

Item {
    id: page1
    property string origin: "Hello"
    signal mainTrial3(string origin)
    ColumnLayout {
        spacing: 15
        Rectangle {
            width: 100
            height: 62
            color: "red"

            MouseArea {
                anchors.fill: parent
                onClicked: {
                    mainTrial3("origin = from MouseArea")
                }
            }
        }

        Button {
            text: "Sorting and scanning"
            onClicked: {
                mainTrial3(origin = "from Button")
            }
        }
    }
}

//mainTrial3 (with the other signal definition)

This file defines the other signal used to reload the previous qml object. I included it here so that you can see that both signals work when one clicks on the rectangles).

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1

Item {
    id: page3
    property string origin: "Hello"
    signal mainTrial1(string origin)
    GridLayout {
        columnSpacing: 5
        rowSpacing: 5
        columns: 1
        Rectangle {
            width: 100
            height: 62
            color: "blue"

            MouseArea{
                anchors.fill: parent
                onClicked: {
                    mainTrial1(origin = "from MouseArea1")
                }
            }
        }
        Rectangle {
            width: 100
            height: 62
            color: "blue"

            MouseArea{
                anchors.fill: parent
                onClicked: {
                    mainTrial1("from MouseArea2")
                }
            }
        }
    }
}
like image 910
Bandung Avatar asked Nov 01 '22 05:11

Bandung


1 Answers

Ok so I took your code, used a bit, and customized the rest to load a single tab to make talking around it a bit easier. It's not exactly what you posted but it should show you how to:

  1. receive the signal when something is clicked inside your tab.
  2. where and how to load your tabs.

With this you should have solid foundation to further customize and add in two, three, etc... tabs and dynamically change them based upon the signals in my example.

Importantly, Tab itself is a Loader so there is no need to define a inner Loader. Next I'm not entirely experienced with QML yet (QWidget is more my thing) but the Connections that you are using seemed to cause some problems, I'm not sure their entirely needed, so I removed them from my example.

In my example I just load a single QML file in a tab and send a signal when you click on either the blue rectangle or the red rectangle inside the tab that was just loaded.

You'll be able to see the print out in the console. I've left a comment in the signal handler where you could then change the source of the Tab and dynamically load the next Tab.

Enjoy!

TabViewTest.qml

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1


Item {
    id: tabViewTest
    width: 360
    height: 360

    TabView {
        id: tabView
        width: parent.width
        height: parent.height

        Tab {
            title: "Welcome"
            id: dynamicTab
            anchors.top: parent.top

            // [1] Specify the source URL to load the content.
            source: "RectanglesTab.qml"

            // [2] Define a signal within the Tab that will
            // be connected to the 'contentsClicked' signal
            // in each tab QML file.
            signal tabContentsClicked( string rectColor )

            // [3] Implement the signal handler.
            onTabContentsClicked: {
                console.log( "Clicked on a", rectColor, "rectangle." )

                // [4] Now that the user has clicked somewhere within the tab
                // you could optionally the source or sourceComponent here like
                // the comment below.
                //
                // Just make sure it also has a signal called 'contentsClicked'
                //
                // dynamicTab.source = "someOtherTab.qml"
            }

            onLoaded: {
                console.debug( "Loaded", source );

                // [4] Here's the key action, connect the signal 
                // 'contentsClicked' to our signal 
                // 'tabContentsClicked' from the loaded item 
                // i.e. RectanglesTab.qml
                dynamicTab.item.contentsClicked.connect(tabContentsClicked)
            }
        }

        Tab {
            id: statusTab
            title: "Status"
        }
    }
}

RectanglesTab.qml

import QtQuick 2.0
import QtQuick.Layouts 1.1

Rectangle {
    id: rectanglesTab
    width: parent.width
    height: parent.height
    color: "black"

    signal contentsClicked( string rectColor )

    GridLayout {
        width: parent.width
        height: parent.height
        columnSpacing: 5
        rowSpacing: 5
        columns: 1
        Rectangle {
            width: parent.width
            height: 120
            color: "blue"

            MouseArea{
                anchors.fill: parent
                onClicked: {
                    contentsClicked( "blue" )
                }
            }
        }
        Rectangle {
            width: parent.width
            height: 120
            color: "red"

            MouseArea{
                anchors.fill: parent
                onClicked: {
                    contentsClicked( "red" )
                }
            }
        }
    }
}
like image 199
Matthew Avatar answered Nov 08 '22 04:11

Matthew