我试图在tablewidget的水平(列)标题中放置一个复选框。百度很久后我试过这个:
失败方法一:
- item = QtGui.QTableWidgetItem()
- item.setCheckState(QtCore.Qt.Checked)
- self.tableWidget.setHorizontalHeaderItem(1, item)
复制代码
我也试过这个:
失败方法二:
- self.tableWidget.horizontalHeaderItem(1).setCheckState(QtCore.Qt.Checked)
复制代码
上面两个方法,这些都不会在表头水平标题中生成一个复选框。
后来查到需要用tableView的方法来设置表头,首先定义一个CheckBoxHeader类,设置表头中加入复选框、信号和信号槽方法。
演示效果
代码说明
- 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()
复制代码
|