Ad

PySide2 QListView QTableView Sync Problem

It is python/PySide2 interface related problem, as much as I tried, I couldn't make it sync (QListView and QTableView).

I will try to simplify it, instead of explaining the whole complicated thing which is much bigger with full of forms stuff in QT...

Just imagine to have a data structure (I guess, model) like the following:

dict_of_dicts={
'dict1':{'k1':'v1', 'k2':'v2', 'k3':'v3'},
'dict2':{'k4':'v4'},
'dict3':{'k5':'v5', 'k6':'v6', 'k7':'v7'},
}

I would like to have a form (or dialog), with 2 parts:

1) In the left of the form, to have a QListView to visualize the following:

*dict1
------
dict2
-----
dict3

NOTES:

  • The asterisk in the dict1 means that is selected.

  • The hyphens are just to separate between rows.

2) In the right of the form, to have a QTableView showing the following:

k1 | v1
-------
k2 | v2
-------
k3 | v3

NOTES:

  • The hyphens are just to separate between rows.

  • The pipes, are just to represent the columns separation.

  • Everytime you select the another element int the QListView, the QTableView must change to the one indicated by the original data structure.

I am sure it could be really easy for most of you guys, but I am just starting with UI stuff and MVC.

Ad

Answer

You have to create a model with the tree structure where the dependency is seen, and in the case of the QListView it will show the root items and in the case of the QTableView it will show the leaves and it will have as rootIndex the selected QModelIndex of the QListView. For educational purposes I will show the model of the tree in a QTreeView.

from PySide2 import QtCore, QtGui, QtWidgets

dict_of_dicts={
    'dict1':{'k1':'v1', 'k2':'v2', 'k3':'v3'},
    'dict2':{'k4':'v4'},
    'dict3':{'k5':'v5', 'k6':'v6', 'k7':'v7'},
}

def create_model_from_dict(d, parent=None):
    model = QtGui.QStandardItemModel(0, 2, parent)
    for k, v in dict_of_dicts.items():
        it = QtGui.QStandardItem(k)
        model.appendRow(it)
        for k_, v_ in v.items():
            it.appendRow([QtGui.QStandardItem(k_), QtGui.QStandardItem(v_)])
    return model

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        model = create_model_from_dict(dict_of_dicts, self)

        self.tableview = QtWidgets.QTableView()
        self.tableview.setModel(model)

        self.listview = QtWidgets.QListView()
        self.listview.setModel(model)
        self.listview.selectionModel().selectionChanged.connect(self.handleSelectionChanged)
        self.listview.selectionModel().select(model.index(0, 0), QtCore.QItemSelectionModel.Select)

        self.treeview = QtWidgets.QTreeView()
        self.treeview.setModel(model)
        self.treeview.expandAll()

        hlay = QtWidgets.QHBoxLayout(self)
        hlay.addWidget(self.listview)
        hlay.addWidget(self.tableview)
        hlay.addWidget(self.treeview)

    @QtCore.Slot(QtCore.QItemSelection)
    def handleSelectionChanged(self, item):
        ixs = item.indexes()
        if ixs:
            self.tableview.setRootIndex(ixs[0])

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

enter image description here

enter image description here

enter image description here

Ad
source: stackoverflow.com
Ad