From 10:00 CET Friday 22nd November we will adjust how the server works to deal with some recently reported problems. Therefore there may be a load problem, if you experience more problems than usual trying to access the forum then please PM AndyS or any of the moderators so they can inform me.


Adding TabButton dynamically to TabBar



  • I am trying to add a tabButton to TabBar dynamically on pressing a button but i have spent a lot of time searching but i am not getting how to add, below is the code which i am working on :

    MyTabButton.qml

    import QtQuick 2.4
    import QtQuick.Controls 2.2
    
    Item
    {
        property int BtnWidth:0
        property int BtnHeight:0
        property string BtnText: ""
        property bool isChecked : false
    
        TabButton
        {
            id:tabBtn
            text:BtnText
            width:BtnWidth
            height:BtnHeight
    
        }
    }
    

    MainForm.qml

    import QtQuick 2.4
    import QtQuick.Controls 2.2
    
    Rectangle
    {
        Button
        {
            id:button
            width:100
            height:100
            anchors.top:parent.top
            text:qStr("Add")
            onClicked{
                //How to add logic here to add tab in below tabBar.
            }
        }
        TabBar
        {
            id:tabBar
            anchors.top:button.bottom
            width:500
            height:500
        }
    }
    


  • @LeLev In my question, you can see that TabButton is created in a separate file. So, based on index changed event I need to do some stuff inside doSomething() on all the TabButtons present in the TabBar.

    I got the solution by using the Component as below :

    in MainForm.Qml

    Component {
           id: myTabButton
           MyTabButton {
               Connections {
                   target: tabBar
                   onCurrentIndexChanged: doSomething()
               }
          }
       }
    
    Button
       {
           id:button
           width:100
           height:100
           anchors.top:parent.top
           text:qStr("Add")
           onClicked{
           // A object out of the component, and adding it to the container
           onClicked: tabBar.addItem(myTabButton.createObject(tabBar /*, { object to set properties }*/))
       }
    

    Thus Whenever an index is changed doSomething function will be called.



  • Hello,

    this is one way to do that using Repeater type.

    import QtQuick 2.0
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.0
    import QtQuick.Layouts 1.3

    Window {
    visible: true
    width: 640
    height: 480

        Button
        {
            id:button
            width:100
            height:100
            anchors.top:parent.top
            text:"add"//qStr("Add")
            onClicked:{
    
                    tabBtnRepeater.model ++
    
            }
        }
    
        TabBar
        {
            id:tabBar
            anchors.top:button.bottom
            width:500
            height:500
    
            Repeater{
                id: tabBtnRepeater
    
                model : 0 //
    
                TabButton{
                    width: 100
                    text: "Btn n° " + index
                }
    
            }
    
    
        }
    }
    

    LA



  • @LeLev .. Thanks for the answer and Is there any way to get the each TabButton item which is created in Repeater ? .
    I need to call some function on the fly in "TabBar" curentIndexChanged event handler ..



  • @pra7

    I cant understant what exactly are you trying to do.

    in "TabBar" curentIndexChanged event handler i guess you will do some action depending which button is clicked right ?

    You can do that by simply adding an 'onClicked' handler on your TabButton like this :

    TabButton{
    width: 100
    text: "Btn n° " + index
    onClicked { console.log(index) } // for exemple
    }

    LA



  • This can help you to access repeater Itemes:
    https://stackoverflow.com/questions/13270818/how-to-access-the-properties-of-a-repeaters-children-in-qml

    and this, if you want to try an other approche (Dynamic Qml Object creation )
    http://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html

    LA





  • @LeLev In my question, you can see that TabButton is created in a separate file. So, based on index changed event I need to do some stuff inside doSomething() on all the TabButtons present in the TabBar.

    I got the solution by using the Component as below :

    in MainForm.Qml

    Component {
           id: myTabButton
           MyTabButton {
               Connections {
                   target: tabBar
                   onCurrentIndexChanged: doSomething()
               }
          }
       }
    
    Button
       {
           id:button
           width:100
           height:100
           anchors.top:parent.top
           text:qStr("Add")
           onClicked{
           // A object out of the component, and adding it to the container
           onClicked: tabBar.addItem(myTabButton.createObject(tabBar /*, { object to set properties }*/))
       }
    

    Thus Whenever an index is changed doSomething function will be called.



  • @LeLev Thanks for all your suggestions....



  • You are welcome :)



  • Full version with normal 'TabButton' :

    import QtQuick 2.0
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.0
    import QtQuick.Layouts 1.3

    Window {
    visible: true
    width: 640
    height: 480

    function doSomething(){
        console.log(tabBar.currentIndex)
    }
    
    Component {
           id: myTabButton
           TabButton {
               Connections {
                   target: tabBar
                   onCurrentIndexChanged: doSomething()
               }
          }
       }
    
    
        Button
        {
            id:button
            width:100
            height:100
            anchors.top:parent.top
            text:"add"
            onClicked:{
                    tabBar.addItem(myTabButton.createObject(tabBar ))
                
            }
        }
    
        TabBar
        {
            id:tabBar
            anchors.top:button.bottom
            width:500
            height:500
    
        }
    }
    

    I'm still intrigued by one thing ! why doSomething() is called 2 times ??
    LA



  • It is not called 2 times but 'addedButtonNumber' times

    if we have 2 btns it is called 2 times
    if we have 3, 3 times and so on

    LA



  • @LeLev Yes .. it will be called based on TabBar.Count ...



  • @pra7 createObject may be the best solution for you. As an exercise I tried another way:

    import QtQuick 2.6
    import QtQuick.Layouts 1.3
    import QtQuick.Controls 2.1
    
    ApplicationWindow {
        id: window
        width: 360
        height: 520
        visible: true
    
    
        ColumnLayout
        {
            Button
            {
                id:button
                text:"add"
                onClicked: {
                    control.contentItem.model.append({"text":"x"})
                }
            }
            TabBar
            {
                {
                Layout.fillWidth: true
                id: control
    
                contentItem: ListView {
                    implicitWidth: contentWidth
                    implicitHeight: 40
    
                    model: ListModel{}
                    delegate: TabButton{text:model.modelData}
                    currentIndex: control.currentIndex
    
                    spacing: control.spacing
                    orientation: ListView.Horizontal
                    boundsBehavior: Flickable.StopAtBounds
                    flickableDirection: Flickable.AutoFlickIfNeeded
                    snapMode: ListView.SnapToItem
    
                    highlightMoveDuration: 0
                    highlightRangeMode: ListView.ApplyRange
                    preferredHighlightBegin: 40
                    preferredHighlightEnd: width - 40
                }
            }
        }
    }
    

    The TabBar code is taken partly from Default style's TabBar.qml to make it look and behave indentically.


  • Qt Champions 2018

    Simpler alternative, just a Repeater with a ListModel inside TabBar :

    import QtQuick 2.0
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.0
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
    
        ListModel {
            id: tabModel
        }
    
        TabBar
        {
            Repeater {
                model: tabModel
                TabButton {
                    text: model.text + " " + model.index
                    onClicked: tabModel.remove(model.index)
                }
            }
        }
    
        Button
        {
            anchors.centerIn: parent
            text:"add"
            onClicked: tabModel.append({text: "tab"});
        }
    }
    

    EDIT: My bad, I didn't saw @LeLev first answer, it's very similar to mine. But I fell compelled to post it cause there's a lot of over complicated code in the following answers.