import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class CheckBoxHeader(QHeaderView):
clicked = pyqtSignal(int, bool)
_x_offset = 3
_y_offset = 0
_width = 20
_height = 20
def __init__(self, column_indices, orientation=Qt.Horizontal, parent=None):
super(CheckBoxHeader, self).__init__(orientation, parent)
self.setSectionResizeMode(QHeaderView.Stretch)
self.setSectionsClickable(True)
if isinstance(column_indices, list) or isinstance(column_indices, tuple):
self.column_indices = column_indices
elif isinstance(column_indices, int):
self.column_indices = [column_indices]
else:
raise RuntimeError('column_indices must be a list, tuple or integer')
self.isChecked = {}
for 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 = QStyleOptionButton()
option.rect = QRect(rect.x() + self._x_offset, rect.y() + self._y_offset, self._width, self._height)
option.state = QStyle.State_Enabled | QStyle.State_Active
if self.isChecked[logicalIndex] == 2:
option.state |= QStyle.State_NoChange
elif self.isChecked[logicalIndex]:
option.state |= QStyle.State_On
else:
option.state |= QStyle.State_Off
self.style().drawControl(QStyle.CE_CheckBox, option, painter)
def updateCheckState(self, index, state):
'''
记录每个点击checkbox 状态及序号存入dict
:param index:
:param state:
:return:
'''
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 and 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):
for i in range(model.rowCount()):
item = model.item(i, index)
item.setCheckState(Qt.Checked if state else Qt.Unchecked)
def modelChanged():
for i in range(model.columnCount()):
checked = 0
unchecked = 0
for j in range(model.rowCount()):
if model.item(j, i).checkState() == Qt.Checked:
checked += 1
elif model.item(j, i).checkState() == Qt.Unchecked:
unchecked += 1
if checked and unchecked:
header.updateCheckState(i, 2)
elif checked:
header.updateCheckState(i, 1)
else:
header.updateCheckState(i, 0)
app = QApplication(sys.argv)
tableView = QTableView()
model = QStandardItemModel()
model.itemChanged.connect(modelChanged)
model.setHorizontalHeaderLabels(['全选', '学号', '姓名', '性别', '籍贯'])
header = CheckBoxHeader([0], parent=tableView)
header.clicked.connect(updateModel)
# populate the models with some items
for i in range(5):
item1 = QStandardItem()
item1.setCheckable(True)
item2 = QStandardItem('lyyd_%d' % i)
item3 = QStandardItem('张三%d' % i)
item4 = QStandardItem('女')
item5 = QStandardItem('北京%d' % i)
model.appendRow([item1, item2, item3, item4, item5])
tableView.setModel(model)
tableView.setHorizontalHeader(header)
# tableView.setSortingEnabled(True)
tableView.show()
sys.exit(app.exec_())
- 1
- 2
- 3
- 4
- 5
前往页