检查影响 QListWidget 中特定项目集的项目
Check an item that effects on a certain set of items within QListWidget
我有一个已创建并添加到 QListWidget 的项目列表,其中这些项目是 'categorized'。
在我的以下代码中,我有 2 个类别 - -- All Nums --
和 -- All Letters --
。在每个类别中,它都有其子项。
由于我已将所有项目设为可检查,是否可以 check/uncheck 这些 header 项目并对其子项目产生影响?
例如。如果我检查 -- All Nums
,所有 num_items
也将被检查。如果我取消选中它,它们也会取消选中。
class TestDialog(QtGui.QDialog):
def __init__(self, parent=None):
super(TestDialog, self).__init__()
self.listWidget = QtGui.QListWidget()
all_num = QtGui.QListWidgetItem('-- All Nums --')
self.listWidget.addItem(all_num)
num_items = ['One', 'Two', 'Three']
for num in num_items:
self.listWidget.addItem(num)
all_letters = QtGui.QListWidgetItem('-- All Letters --')
self.listWidget.addItem(all_letters)
letter_items = ['One', 'Two', 'Three']
for letter in letter_items:
self.listWidget.addItem(letter)
for index in range(self.listWidget.count()):
item = self.listWidget.item(index)
item.setFlags(
item.flags() |
QtCore.Qt.ItemIsUserCheckable |
QtCore.Qt.ItemIsEditable
)
item.setCheckState(QtCore.Qt.Unchecked)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.listWidget)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = TestDialog()
w.show()
sys.exit(app.exec_())
解决思路是用一个role来存储item是否是category的信息,用另一个role来表示item之间的亲缘关系,如果满足则用delegate修改.
from PyQt4 import QtCore, QtGui
IsCategoryRole = QtCore.Qt.UserRole
ParentRole = QtCore.Qt.UserRole + 1
class CategoryDelegate(QtGui.QStyledItemDelegate):
def editorEvent(self, event, model, option, index):
old_state = model.data(index, QtCore.Qt.CheckStateRole)
res = super(CategoryDelegate, self).editorEvent(
event, model, option, index
)
current_state = model.data(index, QtCore.Qt.CheckStateRole)
if old_state != current_state:
if index.data(IsCategoryRole):
pix = QtCore.QPersistentModelIndex(index)
for i in range(model.rowCount()):
ix = model.index(i, 0)
if pix == ix.data(ParentRole):
model.setData(
ix, current_state, QtCore.Qt.CheckStateRole
)
return res
class ListWidget(QtGui.QListWidget):
def __init__(self, parent=None):
super(ListWidget, self).__init__(parent)
delegate = CategoryDelegate(self)
self.setItemDelegate(delegate)
def addCategory(self, text):
item = ListWidget.create_checkable_item(text)
item.setData(IsCategoryRole, True)
self.addItem(item)
return item
def addItemToCategory(self, category_item, text):
item = ListWidget.create_checkable_item(text)
item.setData(IsCategoryRole, False)
ix = self.indexFromItem(category_item)
pix = QtCore.QPersistentModelIndex(ix)
item.setData(ParentRole, pix)
self.addItem(item)
return item
@staticmethod
def create_checkable_item(text):
item = QtGui.QListWidgetItem(text)
item.setFlags(
item.flags()
| QtCore.Qt.ItemIsUserCheckable
| QtCore.Qt.ItemIsEditable
)
item.setCheckState(QtCore.Qt.Unchecked)
return item
class TestDialog(QtGui.QDialog):
def __init__(self, parent=None):
super(TestDialog, self).__init__()
self.listWidget = ListWidget()
all_num = self.listWidget.addCategory("-- All Nums --")
num_items = ["One", "Two", "Three"]
for num in num_items:
self.listWidget.addItemToCategory(all_num, num)
all_letters = self.listWidget.addCategory("-- All Letters --")
letter_items = ["One", "Two", "Three"]
for letter in letter_items:
self.listWidget.addItemToCategory(all_letters, letter)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.listWidget)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = TestDialog()
w.show()
sys.exit(app.exec_())
我有一个已创建并添加到 QListWidget 的项目列表,其中这些项目是 'categorized'。
在我的以下代码中,我有 2 个类别 - -- All Nums --
和 -- All Letters --
。在每个类别中,它都有其子项。
由于我已将所有项目设为可检查,是否可以 check/uncheck 这些 header 项目并对其子项目产生影响?
例如。如果我检查 -- All Nums
,所有 num_items
也将被检查。如果我取消选中它,它们也会取消选中。
class TestDialog(QtGui.QDialog):
def __init__(self, parent=None):
super(TestDialog, self).__init__()
self.listWidget = QtGui.QListWidget()
all_num = QtGui.QListWidgetItem('-- All Nums --')
self.listWidget.addItem(all_num)
num_items = ['One', 'Two', 'Three']
for num in num_items:
self.listWidget.addItem(num)
all_letters = QtGui.QListWidgetItem('-- All Letters --')
self.listWidget.addItem(all_letters)
letter_items = ['One', 'Two', 'Three']
for letter in letter_items:
self.listWidget.addItem(letter)
for index in range(self.listWidget.count()):
item = self.listWidget.item(index)
item.setFlags(
item.flags() |
QtCore.Qt.ItemIsUserCheckable |
QtCore.Qt.ItemIsEditable
)
item.setCheckState(QtCore.Qt.Unchecked)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.listWidget)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = TestDialog()
w.show()
sys.exit(app.exec_())
解决思路是用一个role来存储item是否是category的信息,用另一个role来表示item之间的亲缘关系,如果满足则用delegate修改.
from PyQt4 import QtCore, QtGui
IsCategoryRole = QtCore.Qt.UserRole
ParentRole = QtCore.Qt.UserRole + 1
class CategoryDelegate(QtGui.QStyledItemDelegate):
def editorEvent(self, event, model, option, index):
old_state = model.data(index, QtCore.Qt.CheckStateRole)
res = super(CategoryDelegate, self).editorEvent(
event, model, option, index
)
current_state = model.data(index, QtCore.Qt.CheckStateRole)
if old_state != current_state:
if index.data(IsCategoryRole):
pix = QtCore.QPersistentModelIndex(index)
for i in range(model.rowCount()):
ix = model.index(i, 0)
if pix == ix.data(ParentRole):
model.setData(
ix, current_state, QtCore.Qt.CheckStateRole
)
return res
class ListWidget(QtGui.QListWidget):
def __init__(self, parent=None):
super(ListWidget, self).__init__(parent)
delegate = CategoryDelegate(self)
self.setItemDelegate(delegate)
def addCategory(self, text):
item = ListWidget.create_checkable_item(text)
item.setData(IsCategoryRole, True)
self.addItem(item)
return item
def addItemToCategory(self, category_item, text):
item = ListWidget.create_checkable_item(text)
item.setData(IsCategoryRole, False)
ix = self.indexFromItem(category_item)
pix = QtCore.QPersistentModelIndex(ix)
item.setData(ParentRole, pix)
self.addItem(item)
return item
@staticmethod
def create_checkable_item(text):
item = QtGui.QListWidgetItem(text)
item.setFlags(
item.flags()
| QtCore.Qt.ItemIsUserCheckable
| QtCore.Qt.ItemIsEditable
)
item.setCheckState(QtCore.Qt.Unchecked)
return item
class TestDialog(QtGui.QDialog):
def __init__(self, parent=None):
super(TestDialog, self).__init__()
self.listWidget = ListWidget()
all_num = self.listWidget.addCategory("-- All Nums --")
num_items = ["One", "Two", "Three"]
for num in num_items:
self.listWidget.addItemToCategory(all_num, num)
all_letters = self.listWidget.addCategory("-- All Letters --")
letter_items = ["One", "Two", "Three"]
for letter in letter_items:
self.listWidget.addItemToCategory(all_letters, letter)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.listWidget)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = TestDialog()
w.show()
sys.exit(app.exec_())