Issue
How can i make it so when a user clicks on the checkbox within the selected items, it changes all the selected items in the treeview to match the state of the clicked checkbox? The item that is clicked.
As an example, when i click Jason, it should toggle all the other items selected to also be checked. However what currently happens instead, is Jason becomes the only item selected and checked.
Before clicking Jason:
Result currently after clicking Jason:
What i would like to happen:
import sys
import os
from PySide import QtGui, QtCore
class Example(QtGui.QDialog):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
self.resize(300, 300)
self.setWindowTitle('Example')
self.ui_items = QtGui.QTreeView()
self.ui_items.sortByColumn(1, QtCore.Qt.AscendingOrder)
self.ui_items.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.ui_items.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.ui_items.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.ui_items.setModel(QtGui.QStandardItemModel())
grid = QtGui.QGridLayout()
grid.setContentsMargins(0, 0, 0, 0)
grid.addWidget(self.ui_items, 0, 0)
self.setLayout(grid)
self.setLayout(grid)
self.create_model()
def create_model(self):
model = self.ui_items.model()
model.clear()
model.setHorizontalHeaderLabels(['Items'])
self.ui_items.sortByColumn(0, QtCore.Qt.AscendingOrder)
data = {
'Family 01': ['Amy', 'Kevin'],
'Family 02': ['Sarah', 'Jason', 'Abby'],
'Family 03': ['Michelle', 'Mike', 'Scott', 'Allie']
}
for k, v in data.items():
root = []
# family
root_node = QtGui.QStandardItem()
root_node.setData(k, role=QtCore.Qt.DisplayRole)
root.append(root_node)
# children
for child in v:
row = []
row_node = QtGui.QStandardItem()
row_node.setData(child, role=QtCore.Qt.DisplayRole)
row_node.setCheckable(True)
row.append(row_node)
root_node.appendRow(row)
model.appendRow(root)
self.ui_items.expandAll()
self.ui_items.resizeColumnToContents(0)
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Solution
The first step is connecting to a signal that is emitted when the state of an item changes.
This can be achieved by:
model = self.ui_items.model()
model.itemChanged.connect(self.handle_statechange)
These lines have to be inserted somewhere after your setModel() command. handle_statechange is the name of a method that you will have to define:
def handle_statechange(self, checked_item):
state = checked_item.checkState()
indices = self.ui_items.selectedIndexes()
for idx in indices:
item = idx.model().itemFromIndex(idx)
item.setCheckState(state)
Edit: Eyllanesc comments that clicking on a check box deselects all items besides the one with the clicked checkbox. That's the normal behavior, which you can avoid as a user by keeping the "Ctrl"-button clicked. I dont't know if and how you can override this standard behavior as a programmer.
Answered By - Frank from Frankfurt
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.