Может ли QListWidget иметь группировки?
В настоящее время у меня есть QListWidget, который отображает много элементов, которые выбираются пользователем (и перетаскиваются). В моем приложении, когда элемент отмечен, он будет переупорядочен над непроверенными элементами. Пользователь также может перетащить / отпустить, чтобы настроить порядок отмеченных пунктов.
Проблема, с которой сталкиваются пользователи, состоит в том, что существует множество этих флажков, и они не сгруппированы логически на экране. Таким образом, я хотел бы представить группировку какой-то. Вот пример того, как это работает в настоящее время.
from PyQt4 import QtGui, QtCore
import sys
rows = [
{'text': 'Row1', 'value': 1, 'group': 1},
{'text': 'Row2', 'value': 2, 'group': 1},
{'text': 'Row3', 'value': 3, 'group': 1},
{'text': 'Row4', 'value': 4, 'group': 2},
{'text': 'Row5', 'value': 5, 'group': 2},
{'text': 'Row6', 'value': 6, 'group': 3},
{'text': 'Row7', 'value': 7, 'group': 3},
{'text': 'Row8', 'value': 8, 'group': 3},
{'text': 'Row9', 'value': 9, 'group': 2},
{'text': 'Row10', 'value': 10, 'group': 'testing'}
]
class MyList(QtGui.QListWidget):
def __init__(self):
QtGui.QListWidget.__init__(self)
for row in rows:
item = QtGui.QListWidgetItem(row['text'])
# These are utilizing the ItemDataRole; 33 and 34 are among the first user defined values
# http://pyqt.sourceforge.net/Docs/PyQt4/qt.html#ItemDataRole-enum
item.setData(33, row['value'])
item.setData(34, row['group'])
item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
item.setCheckState(QtCore.Qt.Unchecked)
self.addItem(item)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
my_list = MyList()
my_list.show()
sys.exit(app.exec_())
Это создает приложение, подобное этому:
То, что я хочу сделать, это сгруппировать элементы, которые имеют похожие группы под сходным заголовком. Когда элемент отмечен, он появляется над группами. Первоначально это выглядит как QTreeWidget/View, за исключением того, что отмеченные элементы должны появляться за пределами существующего дерева.
Пример (вывод текста):
[CHECKED ITEMS APPEAR HERE]
Group 1
Row1
Row2
Row3
Group 2
Row4
Row5
Row9
Group 3
Row6
Row7
Row8
Group testing
Row10
Есть ли способ сгруппировать элементы в QListWidget, предпочтительно, чтобы можно было выбрать "заголовок" и выбрать все дочерние элементы?
1 ответ
Чтобы перечислить элементы в группах, здесь стоит вопрос: как перечислять элементы как группы в QListWidget
если элементы заголовка и обычные элементы отличаются в одном свойстве, они могут обрабатываться по-разному в слоте. Я не совсем уверен, если это так, как вы хотите. Я попытался разместить отмеченные элементы сверху и выбрать все элементы группы, щелкнув по элементу заголовка.
Выбор другого сигнала и изменение слота дает много возможностей изменить поведение. Вот мой код (я попробовал это в PyPt5, заменив QtGui на QtWidgets
from PyQt4 import QtGui, QtCore
import sys
rows = [
{'text': 'Row1', 'value': 1, 'group': 1},
{'text': 'Row2', 'value': 2, 'group': 1},
{'text': 'Row3', 'value': 3, 'group': 1},
{'text': 'Row4', 'value': 4, 'group': 2},
{'text': 'Row5', 'value': 5, 'group': 2},
{'text': 'Row6', 'value': 6, 'group': 3},
{'text': 'Row7', 'value': 7, 'group': 3},
{'text': 'Row8', 'value': 8, 'group': 3},
{'text': 'Row9', 'value': 9, 'group': 2},
{'text': 'Row10', 'value': 10, 'group': 'testing'}
]
grouptitles = [1, 2, 3,'testing'] # list of grouptitles
def gruppe(d): # function for sorting the itemlist
return str(d['group'])
rows.sort(key=gruppe,reverse=False) # sort rows by groups
class MyList(QtGui.QListWidget):
def __init__(self):
QtGui.QListWidget.__init__(self)
self.setMinimumHeight(270)
for t in grouptitles:
item = QtGui.QListWidgetItem('Group {}'.format(t))
item.setData(33, 'header')
item.setData(34, t)
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
self.addItem(item)
for row in rows:
if row['group'] == t:
item = QtGui.QListWidgetItem(row['text'])
# These are utilizing the ItemDataRole; 33 and 34 are among the first user defined values
# http://pyqt.sourceforge.net/Docs/PyQt4/qt.html#ItemDataRole-enum
item.setData(33, row['value'])
item.setData(34, row['group'])
item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
item.setCheckState(QtCore.Qt.Unchecked)
self.addItem(item)
else:
pass
self.setSelectionMode(QtGui.QAbstractItemView.MultiSelection) #
self.itemClicked.connect(self.selManager) # select an appropriate signal
def selManager(self, item):
if item.data(33) == 'header':
groupcode = item.data(34)
for i in range(0,self.count()):
if self.item(i).data(34) == groupcode and self.item(i).data(33) != 'header':
b = True if self.item(i).isSelected() == False else False
self.item(i).setSelected(b)
else:
if item.checkState() == QtCore.Qt.Unchecked:
item.setCheckState(QtCore.Qt.Checked)
self.moveItem(self.currentRow(),0)
else:
item.setCheckState(QtCore.Qt.Unchecked)
text = 'Group {}'.format(item.data(34))
new = self.indexFromItem(self.findItems(text, QtCore.Qt.MatchExactly)[0]).row() # find the row of the headeritem
self.moveItem(self.currentRow(), new) # moving back to group
def moveItem(self, old, new): # from row(old) to row(new)
ni = self.takeItem(old)
self.insertItem(new,ni)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
my_list = MyList()
my_list.show()
sys.exit(app.exec_())