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


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



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



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.