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.3Window {
visible: true
width: 640
height: 480Button { 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
-
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-qmland this, if you want to try an other approche (Dynamic Qml Object creation )
http://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.htmlLA
-
-
@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.
-
Full version with normal 'TabButton' :
import QtQuick 2.0
import QtQuick.Window 2.2
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3Window {
visible: true
width: 640
height: 480function 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 -
@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 aListModel
insideTabBar
: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.