How to send signals between tabs of TabView (Qt5)

前端 未结 1 1187
说谎
说谎 2021-01-07 11:21

I have TabView with two tabs. Each tab has Item element (which contains other stuff). I need to send signal from one tab and to catch (to handle) it in other tab.

If

相关标签:
1条回答
  • 2021-01-07 11:32

    You can do it like this:

    import QtQuick 2.3
    import QtQuick.Controls 1.2
    
    Rectangle {
        id: myRect
        width: 100
        height: 100
    
        TabView {
            anchors.fill: parent
    
            Component.onCompleted: {
                tab1.tab1Signal.connect(tab2.onTab1Signal)
                tab2.tab2Signal.connect(tab1.onTab2Signal)
            }
    
            Tab {
                id: tab1
                title: "Tab 1"
    
                signal tab1Signal
    
                function onTab2Signal() {
                    print("Tab 1 received Tab 2's signal")
                }
    
                Item {
                    Button {
                        text: "Send signal"
                        anchors.centerIn: parent
                        onClicked: tab1Signal()
                    }
                }
            }
            Tab {
                id: tab2
                title: "Tab 2"
    
                signal tab2Signal
    
                function onTab1Signal() {
                    print("Tab 2 received Tab 1's signal")
                }
    
                Item {
                    Button {
                        text: "Send signal"
                        anchors.centerIn: parent
                        onClicked: tab2Signal()
                    }
                }
            }
        }
    }
    

    The functions can of course be named anything; I only prefixed them with "on" because that's the convention for signal handler names.

    For more information on connecting signals in QML, see Connecting Signals to Methods and Signals.


    Is it possible to make a onTab1Signal() in Item? I need to send some information (String/int) to elements of Item of tab2.

    Yes, but it's a bit trickier. First of all, remember that Tab is a Loader, so your Item declared inside it may not always be valid. In fact, if you look at the implementation of Tab, you'll see that it sets its active property to false, effectively meaning that tab content is loaded only after that tab has been made current (a design called lazy loading). A naive implementation (i.e my first attempt :p) will encounter strange errors, so you must either:

    1. Set active to true in each Tab, or
    2. Add an intermediate item that accounts for this

    The first solution is the easiest:

    import QtQuick 2.3
    import QtQuick.Controls 1.2
    
    Rectangle {
        id: myRect
        width: 100
        height: 100
    
        TabView {
            id: tabView
            anchors.fill: parent
    
            Component.onCompleted: {
                tab1.tab1Signal.connect(tab2Item.onTab1Signal)
                tab2.tab2Signal.connect(tab1Item.onTab2Signal)
            }
    
            // You can also use connections if you prefer:
    //        Connections {
    //            target: tab1
    //            onTab1Signal: tabView.tab2Item.onTab1Signal()
    //        }
    
    //        Connections {
    //            target: tab2
    //            onTab2Signal: tabView.tab1Item.onTab2Signal()
    //        }
    
            property alias tab1Item: tab1.item
            property alias tab2Item: tab2.item
    
            Tab {
                id: tab1
                title: "Tab 1"
                active: true
    
                signal tab1Signal
    
                Item {
                    id: tab1Item
    
                    function onTab2Signal() {
                        print("Tab 1 received Tab 2's signal")
                    }
    
                    Button {
                        text: "Send signal"
                        anchors.centerIn: parent
                        onClicked: tab1Signal()
                    }
                }
            }
            Tab {
                id: tab2
                title: "Tab 2"
                active: true
    
                signal tab2Signal
    
                Item {
                    function onTab1Signal() {
                        print("Tab 2 received Tab 1's signal")
                    }
    
                    Button {
                        text: "Send signal"
                        anchors.centerIn: parent
                        onClicked: tab2Signal()
                    }
                }
            }
        }
    }
    

    The second solution is slightly more difficult, and comes with a caveat:

    import QtQuick 2.3
    import QtQuick.Controls 1.2
    
    Rectangle {
        id: myRect
        width: 100
        height: 100
    
        TabView {
            id: tabView
            anchors.fill: parent
    
            QtObject {
                id: signalManager
    
                signal tab1Signal
                signal tab2Signal
            }
    
            property alias tab1Item: tab1.item
            property alias tab2Item: tab2.item
    
            Tab {
                id: tab1
                title: "Tab 1"
    
                signal tab1Signal
    
                onLoaded: {
                    tab1Signal.connect(signalManager.tab1Signal)
                    signalManager.tab2Signal.connect(tab1.item.onTab2Signal)
                }
    
                Item {
                    id: tab1Item
    
                    function onTab2Signal() {
                        print("Tab 1 received Tab 2's signal")
                    }
    
                    Button {
                        text: "Send signal"
                        anchors.centerIn: parent
                        onClicked: tab1Signal()
                    }
                }
            }
            Tab {
                id: tab2
                title: "Tab 2"
    
                signal tab2Signal
    
                onLoaded: {
                    tab2Signal.connect(signalManager.tab2Signal)
                    signalManager.tab1Signal.connect(tab2.item.onTab1Signal)
                }
    
                Item {
                    function onTab1Signal() {
                        print("Tab 2 received Tab 1's signal")
                    }
    
                    Button {
                        text: "Send signal"
                        anchors.centerIn: parent
                        onClicked: tab2Signal()
                    }
                }
            }
        }
    }
    

    Because active isn't set to true, the second tab isn't loaded at start up, so it won't receive the first tab's signals until it's made current (i.e by clicking on it). Perhaps that's acceptable for you, so I documented this solution as well.

    0 讨论(0)
提交回复
热议问题