【问题标题】:add feature for previous question PySide2 QListView and QTableView为上一个问题 PySide2 QListView 和 QTableView 添加功能
【发布时间】:2019-01-03 09:36:25
【问题描述】:

上一个问题是PySide2 QListView QTableView sync problem

想象在数据结构中有另一个dict4:

'dict4':{'k8':'v8', 'EXISTING_DICT':'dict2'},

意思是一个字典可以包含另一个现有的字典。

所以QTableView中的表示不应该直接显示,但是:

1) 在 QTableView 中只显示它的名字:

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

2)如果双击它:选择QListView中已有的字典,这将触发在QTableView中显示其内容,在这种情况下:

k4 | v4

【问题讨论】:

    标签: python model-view-controller qtableview qlistview pyside2


    【解决方案1】:

    本例的思路是用一个角色来表示该字段指向另一个item,然后用setSpan连接items,最后通过select if it is so来检查QTableView中选中的item是否指向另一个元素

    from PySide2 import QtCore, QtGui, QtWidgets
    
    dict_of_dicts={
        'dict1':{'k1':'v1', 'k2':'v2', 'k3':'v3', 'EXISTING_DICT': 'dict3'},
        'dict2':{'k4':'v4', 'EXISTING_DICT': 'dict1'},
        'dict3':{'k5':'v5', 'k6':'v6', 'k7':'v7', 'EXISTING_DICT': 'dict4'},
        'dict4':{'k8':'v8', 'EXISTING_DICT':'dict2'},
    }
    
    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():
                if k_ != "EXISTING_DICT":
                    it.appendRow([QtGui.QStandardItem(k_), QtGui.QStandardItem(v_)])
                else:
                    child_it = QtGui.QStandardItem(v_)
                    child_it.setTextAlignment(QtCore.Qt.AlignCenter)
                    child_it.setData(True, QtCore.Qt.UserRole + 1000)
                    it.appendRow(child_it)
        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.tableview.selectionModel().selectionChanged.connect(self.handleSelectionChangedTV)
    
            self.listview = QtWidgets.QListView()
            self.listview.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
            self.listview.setModel(model)
            self.listview.selectionModel().selectionChanged.connect(self.handleSelectionChangedLV)
            self.listview.selectionModel().select(model.index(0, 0), QtCore.QItemSelectionModel.Select)
    
            hlay = QtWidgets.QHBoxLayout(self)
            hlay.addWidget(self.listview)
            hlay.addWidget(self.tableview)
    
        @QtCore.Slot(QtCore.QItemSelection)
        def handleSelectionChangedLV(self, item):
            ixs = item.indexes()
            if ixs:
                self.tableview.setRootIndex(ixs[0])
                model = self.tableview.model()
                self.tableview.clearSpans()
                for r in range(model.rowCount(self.tableview.rootIndex())):
                    index = model.index(r, 0, self.tableview.rootIndex())
                    if index.data(QtCore.Qt.UserRole + 1000):
                        self.tableview.setSpan(r, 0, 1, 2)
    
        @QtCore.Slot(QtCore.QItemSelection)
        def handleSelectionChangedTV(self, item):
            ixs = item.indexes()
            if ixs:
                ix = ixs[0]
                if ix.data(QtCore.Qt.UserRole + 1000):
                    items = self.listview.model().findItems(ix.data())
                    if items:
                        self.tableview.clearSelection()
                        self.listview.selectionModel().select(items[0].index(), QtCore.QItemSelectionModel.ClearAndSelect)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())
    

    更新:

    from PySide2 import QtCore, QtGui, QtWidgets
    
    dict_of_dicts={
        'dict1':{'k1':'v1', 'k2':'v2', 'k3':'v3', 'EXISTING_DICT': 'dict3'},
        'dict2':{'k4':'v4', 'EXISTING_DICT': 'dict1'},
        'dict3':{'k5':'v5', 'k6':'v6', 'k7':'v7', 'EXISTING_DICT': 'dict4'},
        'dict4':{'k8':'v8', 'EXISTING_DICT':'dict2'},
    }
    
    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():
                if k_ != "EXISTING_DICT":
                    it.appendRow([QtGui.QStandardItem(k_), QtGui.QStandardItem(v_)])
                else:
                    child_it = QtGui.QStandardItem(v_)
                    child_it.setTextAlignment(QtCore.Qt.AlignCenter)
                    child_it.setData(True, QtCore.Qt.UserRole + 1000)
                    it.appendRow(child_it)
        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.tableview.doubleClicked.connect(self.handleSelectionChangedTV)
    
            self.listview = QtWidgets.QListView()
            self.listview.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
            self.listview.setModel(model)
            self.listview.selectionModel().selectionChanged.connect(self.handleSelectionChangedLV)
            self.listview.selectionModel().select(model.index(0, 0), QtCore.QItemSelectionModel.Select)
    
            hlay = QtWidgets.QHBoxLayout(self)
            hlay.addWidget(self.listview)
            hlay.addWidget(self.tableview)
    
        @QtCore.Slot(QtCore.QItemSelection)
        def handleSelectionChangedLV(self, item):
            ixs = item.indexes()
            if ixs:
                self.tableview.setRootIndex(ixs[0])
                model = self.tableview.model()
                self.tableview.clearSpans()
                for r in range(model.rowCount(self.tableview.rootIndex())):
                    index = model.index(r, 0, self.tableview.rootIndex())
                    if index.data(QtCore.Qt.UserRole + 1000):
                        self.tableview.setSpan(r, 0, 1, 2)
    
        @QtCore.Slot(QtCore.QModelIndex)
        def handleSelectionChangedTV(self, ix):
            if ix.data(QtCore.Qt.UserRole + 1000):
                items = self.listview.model().findItems(ix.data())
                if items:
                    self.tableview.clearSelection()
                    self.listview.selectionModel().select(items[0].index(), QtCore.QItemSelectionModel.ClearAndSelect)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())
    

    更新2

    from PySide2 import QtCore, QtGui, QtWidgets
    
    dict_of_dicts={
        'dict1':{'k1':'v1', 'k2':'v2', 'k3':'v3', 'EXISTING_DICT': 'dict3'},
        'dict2':{'k4':'v4', 'EXISTING_DICT': 'dict1'},
        'dict3':{'k5':'v5', 'k6':'v6', 'k7':'v7', 'EXISTING_DICT': 'dict4'},
        'dict4':{'k8':'v8', 'EXISTING_DICT':'dict2'},
    }
    
    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():
                if k_ != "EXISTING_DICT":
                    it.appendRow([QtGui.QStandardItem(k_), QtGui.QStandardItem(v_)])
                else:
                    child_it = QtGui.QStandardItem(v_)
                    child_it.setTextAlignment(QtCore.Qt.AlignCenter)
                    child_it.setData(True, QtCore.Qt.UserRole + 1000)
                    it.appendRow(child_it)
        return model
    
    class TableView(QtWidgets.QTableView):
        leftDoubleClicked = QtCore.Signal(QtCore.QModelIndex)
    
        def mouseDoubleClickEvent(self, event):
            super(TableView, self).mouseDoubleClickEvent(event)
            if event.buttons() & QtCore.Qt.LeftButton:
                ix = self.indexAt(event.pos())
                if ix.isValid(): self.leftDoubleClicked.emit(ix)
    
    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 = TableView()
            self.tableview.setModel(model)
            self.tableview.leftDoubleClicked.connect(self.handleSelectionChangedTV)
    
            self.listview = QtWidgets.QListView()
            self.listview.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
            self.listview.setModel(model)
            self.listview.selectionModel().selectionChanged.connect(self.handleSelectionChangedLV)
            self.listview.selectionModel().select(model.index(0, 0), QtCore.QItemSelectionModel.Select)
    
            hlay = QtWidgets.QHBoxLayout(self)
            hlay.addWidget(self.listview)
            hlay.addWidget(self.tableview)
    
        @QtCore.Slot(QtCore.QItemSelection)
        def handleSelectionChangedLV(self, item):
            ixs = item.indexes()
            if ixs:
                self.tableview.setRootIndex(ixs[0])
                model = self.tableview.model()
                self.tableview.clearSpans()
                for r in range(model.rowCount(self.tableview.rootIndex())):
                    index = model.index(r, 0, self.tableview.rootIndex())
                    if index.data(QtCore.Qt.UserRole + 1000):
                        self.tableview.setSpan(r, 0, 1, 2)
    
        @QtCore.Slot(QtCore.QModelIndex)
        def handleSelectionChangedTV(self, ix):
            if ix.data(QtCore.Qt.UserRole + 1000):
                items = self.listview.model().findItems(ix.data())
                if items:
                    self.tableview.clearSelection()
                    self.listview.selectionModel().select(items[0].index(), QtCore.QItemSelectionModel.ClearAndSelect)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-01
      相关资源
      最近更新 更多