我正在尝试找到一种方法来执行以下操作:
当用户单击列表中的项目时,如果进行了选择,它将保留所选项目并更改其所有复选框以与单击的项目的复选框匹配
在单击复选框时保持对项目的选择。当前,当单击选定行中的项目的复选框时,QListView会清除行选择。但是,当用户单击所选行之外的复选框时,它将正确保留选择。仅当用户单击该行而不是复选框时,该选择才会丢失。
有人可以帮助我覆盖单击复选框以实现我的目标时发生的情况吗?
import os, sys
from Qt import QtGui, QtWidgets, QtCore
class CheckableDictionaryListView(QtWidgets.QListView):
def __init__(self, parent=None, **kwargs):
super(CheckableDictionaryListView, self).__init__(parent)
self.resize(300,300)
self.filters = {}
self.proxyModel = QtCore.QSortFilterProxyModel()
self.proxyModel.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.proxyModel.setSourceModel(QtGui.QStandardItemModel())
self.setModel(self.proxyModel)
self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
# Begin
self.setItems(['item 00','item 01','item 02','item 03','item 05','item 06','item 07','item 08','item 09','item 10'])
# Methods
def setItems(self, lst):
model = self.model().sourceModel()
model.clear()
for x in lst:
item = QtGui.QStandardItem()
item.setCheckable(True)
item.setData(x, role=QtCore.Qt.DisplayRole)
model.appendRow(item)
def main():
app = QtWidgets.QApplication(sys.argv)
ex = CheckableDictionaryListView()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
pass
main()
答案 0 :(得分:1)
除了覆盖editorEditor方法之外,还必须使用QAbstractItemView::MultiSelection
作为selectionMode,以防止视图在单击复选框时被单击事件处理:
import os, sys
from Qt import QtGui, QtWidgets, QtCore
class StyledItemDelegate(QtWidgets.QStyledItemDelegate):
def editorEvent(self, event, model, option, index):
last_state = index.data(QtCore.Qt.CheckStateRole)
val = super(StyledItemDelegate, self).editorEvent(
event, model, option, index
)
if last_state != index.data(QtCore.Qt.CheckStateRole):
return True
return val
class CheckableDictionaryListView(QtWidgets.QListView):
def __init__(self, parent=None):
super(CheckableDictionaryListView, self).__init__(parent)
delegate = StyledItemDelegate(self)
self.setItemDelegate(delegate)
self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
self.setSizePolicy(
QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred
)
self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
self.resize(300, 300)
self.proxyModel = QtCore.QSortFilterProxyModel()
self.proxyModel.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.proxyModel.setSourceModel(QtGui.QStandardItemModel(self))
self.setModel(self.proxyModel)
# after set model
self.model().dataChanged.connect(self.onDataChanged)
self.setItems(
[
"item 00",
"item 01",
"item 02",
"item 03",
"item 05",
"item 06",
"item 07",
"item 08",
"item 09",
"item 10",
]
)
def setItems(self, lst):
model = self.model().sourceModel()
model.clear()
for x in lst:
item = QtGui.QStandardItem()
item.setCheckable(True)
item.setData(x, role=QtCore.Qt.DisplayRole)
model.appendRow(item)
@QtCore.Slot("QModelIndex", "QModelIndex", int)
def onDataChanged(self, tl, br, roles):
if QtCore.Qt.CheckStateRole in roles:
if tl == br and tl in self.selectedIndexes():
state = tl.data(QtCore.Qt.CheckStateRole)
self.model().blockSignals(True)
for ix in self.selectedIndexes():
self.model().setData(ix, state, QtCore.Qt.CheckStateRole)
self.model().blockSignals(False)
def main():
app = QtWidgets.QApplication(sys.argv)
app.setStyle("fusion")
ex = CheckableDictionaryListView()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()