纳速健身

标题: [pyqt5][整理创新]pyqt5在QTableWidget表头中加入复选框并实现全选功能 [打印本页]

作者: awagink    时间: 2021-1-12 09:15
标题: [pyqt5][整理创新]pyqt5在QTableWidget表头中加入复选框并实现全选功能
我试图在tablewidget的水平(列)标题中放置一个复选框。百度很久后我试过这个:
失败方法一:
  1. item = QtGui.QTableWidgetItem()
  2. item.setCheckState(QtCore.Qt.Checked)
  3. self.tableWidget.setHorizontalHeaderItem(1, item)
复制代码


我也试过这个:
失败方法二:
  1. self.tableWidget.horizontalHeaderItem(1).setCheckState(QtCore.Qt.Checked)
复制代码

上面两个方法,这些都不会在表头水平标题中生成一个复选框。

后来查到需要用tableView的方法来设置表头,首先定义一个CheckBoxHeader类,设置表头中加入复选框、信号和信号槽方法。

演示效果
(, 下载次数: 0)

(, 下载次数: 0)

代码说明


  1. from PyQt5.QtWidgets import QApplication, QWidget,  QVBoxLayout,  QTableWidget, QCheckBox, QHeaderView, QStyle, QStyleOptionButton, QTableWidgetItem
  2. from PyQt5.QtCore import Qt, pyqtSignal, QRect

  3. # 表头字段,全局变量
  4. header_field = ['全选', '文件名', '文件路径']
  5. # 用来装行表头所有复选框 全局变量
  6. all_header_combobox = []


  7. class CheckBoxHeader(QHeaderView):
  8.     """自定义表头类"""

  9.     # 自定义 复选框全选信号
  10.     select_all_clicked = pyqtSignal(bool)
  11.     # 这4个变量控制列头复选框的样式,位置以及大小
  12.     _x_offset = 0
  13.     _y_offset = 0
  14.     _width = 20
  15.     _height = 20

  16.     def __init__(self, orientation=Qt.Horizontal, parent=None):
  17.         super(CheckBoxHeader, self).__init__(orientation, parent)
  18.         self.isOn = False

  19.     def paintSection(self, painter, rect, logicalIndex):
  20.         painter.save()
  21.         super(CheckBoxHeader, self).paintSection(painter, rect, logicalIndex)
  22.         painter.restore()

  23.         self._y_offset = int((rect.height() - self._width) / 2.)

  24.         if logicalIndex == 0:
  25.             option = QStyleOptionButton()
  26.             option.rect = QRect(rect.x() + self._x_offset, rect.y() + self._y_offset, self._width, self._height)
  27.             option.state = QStyle.State_Enabled | QStyle.State_Active
  28.             if self.isOn:
  29.                 option.state |= QStyle.State_On
  30.             else:
  31.                 option.state |= QStyle.State_Off
  32.             self.style().drawControl(QStyle.CE_CheckBox, option, painter)

  33.     def mousePressEvent(self, event):
  34.         index = self.logicalIndexAt(event.pos())
  35.         if 0 == index:
  36.             x = self.sectionPosition(index)
  37.             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:
  38.                 if self.isOn:
  39.                     self.isOn = False
  40.                 else:
  41.                     self.isOn = True
  42.                     # 当用户点击了行表头复选框,发射 自定义信号 select_all_clicked()
  43.                 self.select_all_clicked.emit(self.isOn)

  44.                 self.updateSection(0)
  45.         super(CheckBoxHeader, self).mousePressEvent(event)

  46.     # 自定义信号 select_all_clicked 的槽方法
  47.     def change_state(self, isOn):
  48.         # 如果行表头复选框为勾选状态
  49.         if isOn:
  50.             # 将所有的复选框都设为勾选状态
  51.             for i in all_header_combobox:
  52.                 i.setCheckState(Qt.Checked)
  53.         else:
  54.             for i in all_header_combobox:
  55.                 i.setCheckState(Qt.Unchecked)
复制代码

然后在UI_init函数中引入
  1.     def UI_init(self):

  2.         self.ui = Ui_MainWindow()
  3.         self.ui.setupUi(self)
  4.         # 方法一:
  5.         header = CheckBoxHeader()               # 实例化自定义表头
  6.         self.ui.tableWidget.setHorizontalHeader(header)            # 设置表头
  7.         header.select_all_clicked.connect(header.change_state)        # 行表头复选框单击信号与槽
复制代码


在设置table数据的时候第一列加入checkbox复选框,这里也可以使用方法一,方法一的checkbox列在设置只能选中行选中的时候,选中效果兼容后面的选中列,不是一个颜色。这里经过研究在tableWedgit里采用方法二比较合适,方法一在tableView中比较合适。

  1.     def show_items_in_table_widget(self,table_data_list):
  2.         '''
  3.         table_data_list的数据再table中显示,list格式,[[1,2],[1,2],[1,2]]
  4.         '''

  5.         # self.ui.tableWidget.clearContents()
  6.         if table_data_list:
  7.             # 重置tablewidget的行数和列数达到清零表格的目的
  8.             self.ui.tableWidget.setRowCount(len(table_data_list))
  9.             self.ui.tableWidget.setColumnCount(len(header_field))

  10.             for row_num in range(len(table_data_list)):  # 注意上面列表中数字加单引号,否则下面不显示(或者下面str方法转化一下即可)

  11.                 item = table_data_list[row_num]

  12.                 # # 方法一:setCellWidget方法,每一行的第一列加入checkbox,需要self.ui.tableWidget.cellWidget(0,0).isChecked()来检测选中状态
  13.                 # checkbox = QCheckBox()
  14.                 # # 将所有的复选框都添加到 全局变量 all_header_combobox 中
  15.                 # all_header_combobox.append(checkbox)
  16.                 # self.ui.tableWidget.setCellWidget(row_num, 0, checkbox)

  17.                 # 方法二:setItem,setCheckState方法,需要self.ui.tableWidget.item(row_num,0).checkState()来检测选中状态
  18.                 check_box = QTableWidgetItem()
  19.                 check_box.setCheckState(QtCore.Qt.Unchecked)
  20.                 all_header_combobox.append(check_box)
  21.                 self.ui.tableWidget.setItem(row_num, 0, check_box)

  22.                 # 向table中第二列和第三列写入数据
  23.                 for index in range(len(item)):
  24.                     temp_item = QTableWidgetItem(str(table_data_list[row_num][index]))
  25.                     # index+1第一列为checkbox在第二列写入数据
  26.                     self.ui.tableWidget.setItem(row_num , index+1, temp_item)
复制代码

  1. class MainWindow(QMainWindow):
  2.     '''程序主函数,名称也可以为其他内容,需要在if name=__main__函数中更改对应名称'''
  3.     def __init__(self, parent=None):
  4.         super(MainWindow, self).__init__(parent)

  5.         # 调用UI_init方法,初始化ui
  6.         self.UI_init()

  7.         # 显示gui,没有则不显示窗口
  8.         self.show()
复制代码







欢迎光临 纳速健身 (https://www.nasue.com/) Powered by Discuz! X3.4