为上一个问题添加功能 PySide2 QListView 和 QTableView
add feature for previous question PySide2 QListView and QTableView
上一题是
假设数据结构中还有一个dict4:
'dict4':{'k8':'v8', 'EXISTING_DICT':'dict2'},
意思是,字典可以包含另一个现有字典。
所以QTableView中的representation不应该直接显示出来,但是:
1) 在 QTableView 中只显示它的名称:
k1 | v1
-------
k2 | v2
-------
k3 | v3
-------
dict2
2) 如果双击它:select QListView 中的现有字典,这将触发在 QTableView 中显示其内容,在这种情况下:
k4 | v4
本例的思路是用一个role来表示该字段指向另一个item,然后用setSpan连接item,最后通过select if is检查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_())
上一题是
假设数据结构中还有一个dict4:
'dict4':{'k8':'v8', 'EXISTING_DICT':'dict2'},
意思是,字典可以包含另一个现有字典。
所以QTableView中的representation不应该直接显示出来,但是:
1) 在 QTableView 中只显示它的名称:
k1 | v1
-------
k2 | v2
-------
k3 | v3
-------
dict2
2) 如果双击它:select QListView 中的现有字典,这将触发在 QTableView 中显示其内容,在这种情况下:
k4 | v4
本例的思路是用一个role来表示该字段指向另一个item,然后用setSpan连接item,最后通过select if is检查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_())