pythonpyqt5qt-signalsqstackedwidgetqt-slot

Automatically create QStackedWidget pages based on Tuple


I'm fairly new to python, and I feel this is an advanced question, with that in mind it might be out of the scope of Stack Exchange. Please bear with me.

I have a QTreeWidget and QStackedWidget. I have populated the QTreeWidget using a tuple

TreeList = ({

    'Header1': ((
        'Item11',
        'Item12',
    )),

    'Header2': ((
        'Item21',
        'Item22'
    ))
})

for key, value in TreeList.items():
    root = QTreeWidgetItem(self.QTreeWidget, [key])
    for val in value:
        root.addChild(QTreeWidgetItem([val]))

I would like to use this same tuple to populate a QStackedWidget with pages that correspond with the QTreeWidget and establish signals and slots with in the same loop. I have tried using:

for key in TreeList['Item1']:
    page = QWidget()
    page.setObjectName(key)
    self.QStackedWidget.addWidget(page)
    print(self.QStackedWidget)

but all of the objects point to the same hex value, which I assume means they are not unique. Perhaps I need to increment the index? In either case I have not been able to figure out how to generate the signals and slots while doing this, since they are being dynamically created and I need unique but predictable names.

The idea is that by simply adding a new category or item to the tuple, the QTreeView, QStackedWidget, and signals / slots are all generated at runtime without having to modify any source code beyond the tuple.

What would be the best way to accomplish this?

Sorry if this is too much, but I figured it might be a good question in case anyone else attempts the same thing at a later time.

EDIT: I'm using Python 3.6 and PyQt5


Solution

  • The idea is to associate the index of the QStackedWidget with the QTreeWidgetItem, so we can use the setData() method of QTreeWidgetItem to save the index, and then recover it with the data() method:

    import sys
    
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    
    class Widget(QWidget):
        def __init__(self, *args, **kwargs):
            QWidget.__init__(self, *args, **kwargs)
            self.tree = QTreeWidget(self)
            self.stack = QStackedWidget(self)
            lay = QHBoxLayout(self)
            lay.addWidget(self.tree)
            lay.addWidget(self.stack)
    
            for key, value in TreeList.items():
                root = QTreeWidgetItem(self.tree, [key])
                for val in value:
                    item = QTreeWidgetItem([val])
                    root.addChild(item)
                    widget = QLabel(val,  self)
                    ix = self.stack.addWidget(widget)
                    item.setData(0, Qt.UserRole, ix)
            self.tree.expandAll()
            self.tree.itemClicked.connect(self.onItemClicked)
    
        def onItemClicked(self, item, column):
            val = item.data(0, Qt.UserRole)
            if val is not None:
                self.stack.setCurrentIndex(val)
    
    TreeList = ({
    
        'Header1': ((
            'Item11',
            'Item12',
        )),
    
        'Header2': ((
            'Item21',
            'Item22'
        ))
    })
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())