PDA

View Full Version : Sharing a QTreeWidget item across two tabs in Pyside2



supratik
13th October 2020, 07:37
I am trying to design a QTabwidget having two tabs in it. The tab should change based on selection from a QComboBox. I have to populate a QTreewidget instance in the two tabs based on the selection from the combo box i.e same tree should be displayed whenever i switch tabs. I tried creating layouts inside tab and added the same Tree to both the layouts. It works for the first time i.e when i switch tabs I can see the same tree in both the tabs.


if(self.ui.comboReportsNew.currentText()=="Synthesis"):
self.leftLayout = QtWidgets.QVBoxLayout()
self.ui.tab_2.setLayout(self.leftLayout)
self.leftLayout.addWidget(self.ReqTree) //self.ReqTree is the QTreeWidget

elif(self.ui.comboReportsNew.currentText()=="Code Coverage"):
self.rightLayout = QtWidgets.QVBoxLayout()
self.ui.tab.setLayout(self.rightLayout)
self.rightLayout.addWidget(self.ReqTree)

Next time i try to do that it gives me warning " Attempting to add Layout to widget which already has a layout". I tried creating logic to check if my tree widget already has layout and if so , delete the old layout and initialize it with new layout but no luck.

Any help will be very appreciated.

Ginsengelf
13th October 2020, 15:30
Hi, when do you execute your code snippet? Each time you change the tab?

Ginsengelf

supratik
13th October 2020, 15:47
Hi, actually each time i change the text in the comboBox...the code snippet is run. Based on the text in the ComboBox I have to change my tabs and show the QTreeWidget

d_stranz
13th October 2020, 18:05
Based on the text in the ComboBox I have to change my tabs and show the QTreeWidget

First, you cannot "share" QTreeWidgetItem instances between two QTreeWidget instances. An item belongs to one or the other.

You are making the common mistake of "confusing the map for the terrain", that is, thinking that the QTreeWidgetItem -is- the data and not just the way that the data is wrapped to show on screen. The map is not the dirt and rocks under your feet, it is only a picture of it. You can have many maps showing the same rock (the data), but there is only one rock (the terrain).

You want to make two QTreeWidget instances, one for each tab, when you first construct the tabs and not each time you switch. It is not possible to "share" the same widget between two parents. When you call addWidget(), you are moving the widget from one tab to the other, you are not sharing it.

The only thing that changing tabs should do is make one widget or the other visible, and QTabWidget takes care of that for you. The errors you are seeing is because you are trying to create a new GUI every time the combo box selection changes.

So what you should be doing is this:

1 - Create a data structure that holds the information you want to display in the trees. Make a method that returns you the correct part of the data structure based on the combo box selection.

2 - When you construct the GUI for the first time (and only the first time), create your tree widgets, layouts, etc. and add them to the tab widget. Save the tree widget pointers as member variables so you can access them later.

3 - When the combo box selection changes, clear each tree's contents, find the new contents from the data structure, and add new QTreeWidgetItems to each tree using that content. Remember that you cannot add the -same- QTreeWidgetItem to both trees - you have make two QTreeWidgetItems, one for each tree. If you add the same item to two trees, then all that does is move it from the first tree to the second. They cannot be shared.

supratik
13th October 2020, 18:30
First of all thanks for this elaborate explanation. It helped me a lot in clearing my misconception.

I am very new to Pyside framework. It will be really helpful if you could help me with the first point i.e Make a method that returns you the correct part of the data structure based on the combo box selection. . I am not very sure how to do it.

How do I add tree widget pointers in Python ?

Is there any other way I can use the same tree in two tabs. The same tree is used in number of places and if I make two trees just for the sake of switching tabs it creates too much confusion in the other parts of code.
Sorry for my less knowledge about Pyside and this forum also.

Thanks again

d_stranz
13th October 2020, 18:51
How do I add tree widget pointers in Python ?

The same way you probably already did it: self.ReqTree = QtWidgets.QTreeWidget, except that now you need two of them, one for each tab.


Make a method that returns you the correct part of the data structure based on the combo box selection.

I don't know what the data is that you are displaying in your tree widget. I assume it is some hierarchical data because you chose a tree to display it. I also assume that, based on the combo box selection, you are only displaying part of the data in the tree, not all of the data.

I am not that good at Python, but a Python list seems like one way to construct a tree-shaped data structure. A list containing lists, which contain lists, and so on. So say your top-level list has five items in it, and the combo box is used to choose one of those five items. You then want to display the list hierarchy that starts with that item.

You have two ways to find that place in the top-level list. If the top-level list items are the same strings you put in the combo box, then it is easy - you just look at each item in the top-level list until you find the match. If the strings in the combo box are not in the list, then you can use the alternative signal from the combo box, the one that returns the integer index of the item that was selected. Using that index, you get the top-level list item at that location.



theList = [[A, [Aa, [a_i, a_ii, a_iii], [a_iv, a_v, a_vi], [a_vii, a_viii, a_ix], ...], [b, [b_i, b_ii], [b_iii, b_iv, b_v]], ...], [B, [Bb, [...]]], ...]


theList at index 0 gives you [A, [Aa, [a_i ...]]] and you build your tree widget items starting there.

You might be using a different data structure, but the idea is the same - find a way to locate the place you want based on the combo box selection, and use that to build the tree.

supratik
13th October 2020, 19:11
Thanks again for the elaborate explanation for the list data structure.
Actually I am reading data from xml file and storing it in form of QTreeWidget with parents and child as the different elements of the tree.
As evident from your post, I have to create two different widgets for two different tabs and I can't switch them between tabs..

I also thought of creating two different tree widgets , but the linkages of the tree in different places of the code was forcing me to not create another instance and just try to switch the same instance between tabs.
But now I guess I have to create two different treewidgets and display them in different tabs , according to the ComboBox selection .

Thanks for the help

d_stranz
13th October 2020, 19:49
If you are reading from an XML file, then I suggest you read the file into a QDomDocument instance. If you keep the data this way, it makes it easy to find an element at any level of the document, using QDomDocument::elementsByTagName(). It is also easy to build the tree from that point - just follow the QDomNodeList down deeper into the document.

supratik
14th October 2020, 06:26
Thanks a lot :)
I created two instances of the QTreeWidget and modified my code.
It was worth learning for newbie like myself.
I will use this forum again and hope to learn more