纳速健身
标题:
[pyqt5][整理创新]pyqt5在QTableWidget表头中加入复选框并实现全选功能
[打印本页]
作者:
awagink
时间:
2021-1-12 09:15
标题:
[pyqt5][整理创新]pyqt5在QTableWidget表头中加入复选框并实现全选功能
我试图在tablewidget的水平(列)标题中放置一个复选框。百度很久后我试过这个:
失败方法一:
item = QtGui.QTableWidgetItem()
item.setCheckState(QtCore.Qt.Checked)
self.tableWidget.setHorizontalHeaderItem(1, item)
复制代码
我也试过这个:
失败方法二:
self.tableWidget.horizontalHeaderItem(1).setCheckState(QtCore.Qt.Checked)
复制代码
上面两个方法,这些都不会在表头水平标题中生成一个复选框。
后来查到需要用tableView的方法来设置表头,首先定义一个CheckBoxHeader类,设置表头中加入复选框、信号和信号槽方法。
演示效果
(, 下载次数: 1)
上传
点击文件名下载附件
(, 下载次数: 0)
上传
点击文件名下载附件
代码说明
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTableWidget, QCheckBox, QHeaderView, QStyle, QStyleOptionButton, QTableWidgetItem
from PyQt5.QtCore import Qt, pyqtSignal, QRect
# 表头字段,全局变量
header_field = ['全选', '文件名', '文件路径']
# 用来装行表头所有复选框 全局变量
all_header_combobox = []
class CheckBoxHeader(QHeaderView):
"""自定义表头类"""
# 自定义 复选框全选信号
select_all_clicked = pyqtSignal(bool)
# 这4个变量控制列头复选框的样式,位置以及大小
_x_offset = 0
_y_offset = 0
_width = 20
_height = 20
def __init__(self, orientation=Qt.Horizontal, parent=None):
super(CheckBoxHeader, self).__init__(orientation, parent)
self.isOn = False
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 == 0:
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.isOn:
option.state |= QStyle.State_On
else:
option.state |= QStyle.State_Off
self.style().drawControl(QStyle.CE_CheckBox, option, painter)
def mousePressEvent(self, event):
index = self.logicalIndexAt(event.pos())
if 0 == index:
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.isOn:
self.isOn = False
else:
self.isOn = True
# 当用户点击了行表头复选框,发射 自定义信号 select_all_clicked()
self.select_all_clicked.emit(self.isOn)
self.updateSection(0)
super(CheckBoxHeader, self).mousePressEvent(event)
# 自定义信号 select_all_clicked 的槽方法
def change_state(self, isOn):
# 如果行表头复选框为勾选状态
if isOn:
# 将所有的复选框都设为勾选状态
for i in all_header_combobox:
i.setCheckState(Qt.Checked)
else:
for i in all_header_combobox:
i.setCheckState(Qt.Unchecked)
复制代码
然后在UI_init函数中引入
def UI_init(self):
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# 方法一:
header = CheckBoxHeader() # 实例化自定义表头
self.ui.tableWidget.setHorizontalHeader(header) # 设置表头
header.select_all_clicked.connect(header.change_state) # 行表头复选框单击信号与槽
复制代码
在设置table数据的时候第一列加入checkbox复选框,这里也可以使用方法一,方法一的checkbox列在设置只能选中行选中的时候,选中效果兼容后面的选中列,不是一个颜色。这里经过研究在tableWedgit里采用方法二比较合适,方法一在tableView中比较合适。
def show_items_in_table_widget(self,table_data_list):
'''
table_data_list的数据再table中显示,list格式,[[1,2],[1,2],[1,2]]
'''
# self.ui.tableWidget.clearContents()
if table_data_list:
# 重置tablewidget的行数和列数达到清零表格的目的
self.ui.tableWidget.setRowCount(len(table_data_list))
self.ui.tableWidget.setColumnCount(len(header_field))
for row_num in range(len(table_data_list)): # 注意上面列表中数字加单引号,否则下面不显示(或者下面str方法转化一下即可)
item = table_data_list[row_num]
# # 方法一:setCellWidget方法,每一行的第一列加入checkbox,需要self.ui.tableWidget.cellWidget(0,0).isChecked()来检测选中状态
# checkbox = QCheckBox()
# # 将所有的复选框都添加到 全局变量 all_header_combobox 中
# all_header_combobox.append(checkbox)
# self.ui.tableWidget.setCellWidget(row_num, 0, checkbox)
# 方法二:setItem,setCheckState方法,需要self.ui.tableWidget.item(row_num,0).checkState()来检测选中状态
check_box = QTableWidgetItem()
check_box.setCheckState(QtCore.Qt.Unchecked)
all_header_combobox.append(check_box)
self.ui.tableWidget.setItem(row_num, 0, check_box)
# 向table中第二列和第三列写入数据
for index in range(len(item)):
temp_item = QTableWidgetItem(str(table_data_list[row_num][index]))
# index+1第一列为checkbox在第二列写入数据
self.ui.tableWidget.setItem(row_num , index+1, temp_item)
复制代码
class MainWindow(QMainWindow):
'''程序主函数,名称也可以为其他内容,需要在if name=__main__函数中更改对应名称'''
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
# 调用UI_init方法,初始化ui
self.UI_init()
# 显示gui,没有则不显示窗口
self.show()
复制代码
欢迎光临 纳速健身 (https://nasue.com/)
Powered by Discuz! X3.4