PySide / PyQt4: Add a checkbox to the QTableWidget Horizontal (column) header

I am trying to check the box in the horizontal (column) header of my table widget. Based on another post here (because the type of the base object is the same), I tried this:

item = QtGui.QTableWidgetItem() item.setCheckState(QtCore.Qt.Checked) self.tableWidget.setHorizontalHeaderItem(1, item) 

and I also tried this:

 self.tableWidget.horizontalHeaderItem(1).setCheckState(QtCore.Qt.Checked) 

None of them create a checkbox in the horizontal header. Suggestions are welcome.

+4
source share
4 answers

This is not all so beautiful, but the solution for this was published in the FAQ on qt-project.org .

I adapted the solution for Python and made some changes suggested in the comments.

 from PyQt4.QtCore import Qt, QRect from PyQt4.QtGui import QTableWidget, QApplication, QHeaderView, QStyleOptionButton, QStyle import sys class MyHeader(QHeaderView): isOn = False def __init__(self, orientation, parent=None): QHeaderView.__init__(self, orientation, parent) def paintSection(self, painter, rect, logicalIndex): painter.save() QHeaderView.paintSection(self, painter, rect, logicalIndex) painter.restore() if logicalIndex == 0: option = QStyleOptionButton() option.rect = QRect(10, 10, 10, 10) if self.isOn: option.state = QStyle.State_On else: option.state = QStyle.State_Off self.style().drawControl(QStyle.CE_CheckBox, option, painter) def mousePressEvent(self, event): self.isOn = not self.isOn self.updateSection(0) QHeaderView.mousePressEvent(self, event) class MyTable(QTableWidget): def __init__(self): QTableWidget.__init__(self, 3, 3) myHeader = MyHeader(Qt.Horizontal, self) self.setHorizontalHeader(myHeader) if __name__ == '__main__': app = QApplication(sys.argv) myTable = MyTable() myTable.show() sys.exit(app.exec_()) 
+4
source

I gave Gary Hughes credit because it actually puts a checkmark in the headline, but I thought that I would go to the post office with my simpler solution if someone wants to do it easily. This is based on the tips I got on the Qt Developer forums:

I subclassed QTableWidget to make checkboxes a child of horizontalHeader () widgets, and manually move checkboxes when the table is resized:

 class custom_table(QtGui.QTableWidget): def __init__(self, parent=None): QtGui.QTableWidget.__init__(self, parent) self.chkbox1 = QtGui.QCheckBox(self.horizontalHeader()) def resizeEvent(self, event=None): super().resizeEvent(event) self.chkbox1.setGeometry(QtCore.QRect((self.columnWidth(0)/2), 2, 16, 17)) 

"(self.columnWidth (0) / 2)" holds the flag in the middle of the column header.

+1
source

In gratitude to Gary for his answer, the version of his verifiable title was changed here, where all sections can be checked separately

 class QCheckableHeader(QHeaderView): def __init__(self, orientation, parent=None): QHeaderView.__init__(self, orientation, parent) self.lisCheckboxes = [] self.sectionCountChanged.connect(self.onSectionCountChanged) def paintSection(self, painter, rect, logicalIndex): print "paintSection", logicalIndex painter.save() QHeaderView.paintSection(self, painter, rect, logicalIndex) painter.restore() painter.save() painter.translate(rect.topLeft()) option = QStyleOptionButton() option.rect = QRect(10, 10, 10, 10) if (len(self.lisCheckboxes) != self.count()): self.onSectionCountChanged(len(self.lisCheckboxes), self.count()) if self.lisCheckboxes[logicalIndex]: option.state = QStyle.State_On else: option.state = QStyle.State_Off self.style().drawControl(QStyle.CE_CheckBox, option, painter) painter.restore() def mousePressEvent(self, event): iIdx = self.logicalIndexAt(event.pos()) self.lisCheckboxes[iIdx] = not self.lisCheckboxes[iIdx] self.updateSection(iIdx) QHeaderView.mousePressEvent(self, event) @QtCore.Slot() def onSectionCountChanged(self, oldCount, newCount): if newCount > oldCount: for i in range(newCount - oldCount): self.lisCheckboxes.append(False) else: self.lisCheckboxes = self.lisCheckboxes[0:newCount] 

Hope this helps someone else but me :-)

0
source

Adapted from qt-blog http://blog.qt.io/blog/2014/04/11/qt-weekly-5-widgets-on-a-qheaderview/

It can also be used to place custom widgets in the title bar.

 # coding=utf-8 from PySide.QtCore import Qt from PySide.QtGui import QHeaderView, QCheckBox from qtpy import QtCore class CustomHeaderView(QHeaderView): def __init__(self, parent=None): QHeaderView.__init__(self, Qt.Horizontal, parent) self.setMovable(True) self.boxes = [] self.sectionResized.connect(self.handleSectionResized) self.sectionMoved.connect(self.handleSectionMoved) def scrollContentsBy(self, dx, dy): super().scrollContentsBy(dx, dy) if dx != 0: self.fixComboPositions() def fixComboPositions(self): for i in range(self.count() + 1): self.boxes[i].setGeometry(self.sectionViewportPosition(i), 0, self.sectionSize(i) - 5, self.height()) @QtCore.Slot() def showEvent(self, e): for i in range(self.count() + 1): if len(self.boxes) <= i: self.boxes.append(QCheckBox(self)) self.boxes[i].setGeometry(self.sectionViewportPosition(i), 0, self.sectionSize(i) - 5, self.height()) self.boxes[i].show() super().showEvent(e) @QtCore.Slot() def handleSectionMoved(self, logical, oldVisualIndex, newVisualIndex): for i in range(min(oldVisualIndex, newVisualIndex),self.count()): logical = self.logicalIndex(i) self.boxes[logical].setGeometry(self.sectionViewportPosition(logical), 0, self.sectionSize(logical) - 5, self.height()) @QtCore.Slot() def handleSectionResized(self, i): for j in range(self.visualIndex(i),self.count()): logical = self.logicalIndex(j) self.boxes[logical].setGeometry(self.sectionViewportPosition(logical), 0, self.sectionSize(logical) - 5, self.height()) self.boxes[logical].updateGeometry() 
0
source

Source: https://habr.com/ru/post/1401908/


All Articles