python - Adding checkBox as vertical header in QtableView -
i trying have qtableview of checkboxes, can use them row selections... have managed that, want header checkbox can check/uncheck or row . have been looking days, couldn't it.
i tried use setheaderdata model, couldn't it. appreciated.
i wasn't particularly happy c++ version @tmoreau ported python didn't:
- handle more 1 column
- handle custom header heights (for example multi-line header text)
- use tri-state checkbox
- work sorting
so fixed of issues, , created example qstandarditemmodel advocate on trying create own model based on qabstracttablemodel.
there still imperfections, welcome suggestions how improve it!
import sys pyqt4 import qtcore, qtgui # header supporting checkboxes left of text of subset of columns # subset of columns specified list of column_indices @ # instantiation time class checkboxheader(qtgui.qheaderview): clicked=qtcore.pyqtsignal(int, bool) _x_offset = 3 _y_offset = 0 # value calculated later, based on height of paint rect _width = 20 _height = 20 def __init__(self, column_indices, orientation = qtcore.qt.horizontal, parent = none): super(checkboxheader, self).__init__(orientation, parent) self.setresizemode(qtgui.qheaderview.stretch) self.setclickable(true) if isinstance(column_indices, list) or isinstance(column_indices, tuple): self.column_indices = column_indices elif isinstance(column_indices, (int, long)): self.column_indices = [column_indices] else: raise runtimeerror('column_indices must list, tuple or integer') self.ischecked = {} column in self.column_indices: self.ischecked[column] = 0 def paintsection(self, painter, rect, logicalindex): painter.save() super(checkboxheader, self).paintsection(painter, rect, logicalindex) painter.restore() # self._y_offset = int((rect.height()-self._width)/2.) if logicalindex in self.column_indices: option = qtgui.qstyleoptionbutton() option.rect = qtcore.qrect(rect.x() + self._x_offset, rect.y() + self._y_offset, self._width, self._height) option.state = qtgui.qstyle.state_enabled | qtgui.qstyle.state_active if self.ischecked[logicalindex] == 2: option.state |= qtgui.qstyle.state_nochange elif self.ischecked[logicalindex]: option.state |= qtgui.qstyle.state_on else: option.state |= qtgui.qstyle.state_off self.style().drawcontrol(qtgui.qstyle.ce_checkbox,option,painter) def updatecheckstate(self, index, state): self.ischecked[index] = state self.viewport().update() def mousepressevent(self, event): index = self.logicalindexat(event.pos()) if 0 <= index < self.count(): x = self.sectionposition(index) if x + self._x_offset < event.pos().x() < x + self._x_offset + self._width , self._y_offset < event.pos().y() < self._y_offset + self._height: if self.ischecked[index] == 1: self.ischecked[index] = 0 else: self.ischecked[index] = 1 self.clicked.emit(index, self.ischecked[index]) self.viewport().update() else: super(checkboxheader, self).mousepressevent(event) else: super(checkboxheader, self).mousepressevent(event) if __name__=='__main__': def updatemodel(index, state): in range(model.rowcount()): item = model.item(i, index) item.setcheckstate(qtcore.qt.checked if state else qtcore.qt.unchecked) def modelchanged(): in range(model.columncount()): checked = 0 unchecked = 0 j in range(model.rowcount()): if model.item(j,i).checkstate() == qtcore.qt.checked: checked += 1 elif model.item(j,i).checkstate() == qtcore.qt.unchecked: unchecked += 1 if checked , unchecked: header.updatecheckstate(i, 2) elif checked: header.updatecheckstate(i, 1) else: header.updatecheckstate(i, 0) app = qtgui.qapplication(sys.argv) tableview = qtgui.qtableview() model = qtgui.qstandarditemmodel() model.itemchanged.connect(modelchanged) model.sethorizontalheaderlabels(['title 1\na second line','title 2']) header = checkboxheader([0,1], parent = tableview) header.clicked.connect(updatemodel) # populate models items in range(3): item1 = qtgui.qstandarditem('item %d'%i) item1.setcheckable(true) item2 = qtgui.qstandarditem('another checkbox %d'%i) item2.setcheckable(true) model.appendrow([item1, item2]) tableview.setmodel(model) tableview.sethorizontalheader(header) tableview.setsortingenabled(true) tableview.show() sys.exit(app.exec_())
Comments
Post a Comment