当前位置: 首页 > article >正文

PySide6如何实现点击TableWidget列表头在该列右侧显示列表选择框筛选列数据

1. 实现的界面效果

鼠标单击选择需要筛选的表格列标题,在列标题右侧出现列表选择框,选中列表选择框的某个数据,相应的表格上就只显示符合筛选条件的数据。

在这里插入图片描述

2. 关键技术

拆分代码,主要介绍实现功能的关键点。

2.1 设置表格列标题的用户鼠标点击事件

TableWidget控件的表格列标题的用户鼠标点击事件设置如下:

        header = self.tableWidget.horizontalHeader()
        header.sectionClicked.connect(self.showFilterComboBox)

2.2 使用comboBox的activated信号

在 Qt 的 QComboBox 控件中,currentIndexChanged(int index) 和 activated(int index) 是两个常用的信号(signal),但它们在触发时机和用途上有所不同。

QComboBox 的 currentIndexChanged 信号来检测用户何时改变了选中项,但是QComboBox 默认索引是0,导致索引是0的文本被选中不会触发currentIndexChanged 信号。activated 信号在用户选择了一个项并且下拉列表关闭时触发,无论这个项是否是之前选中的。所以,最好不要使用currentIndexChanged 信号,而改为使用activated 信号比较好。

使用QComboBox 的currentIndexChanged 信号的时候还会遇到如下的错误。

原来出错的代码

    self.comboBox.currentIndexChanged.connect(self.commitData)
RuntimeError: Failed to connect signal currentIndexChanged(int).

def commitData(self):
        editor = self.sender()
        commit_index = self.comboBox.currentIndex()
        model = self.comboBox.model()
        
        # 找到当前编辑的单元格的索引
        for view in QApplication.instance().allWidgets():
            if isinstance(view, QTableView):
                for index in view.selectionModel().selectedIndexes():
                    if view.indexWidget(index) == editor:
                        commit_index = index
                        break
        
        # 提交数据到模型
        model.setData(commit_index, editor.currentText(), Qt.EditRole)
currentIndexChanged 信号不直接传递新索引。正确的方式是在槽函数中直接访问 comboBox.currentIndex()def on_current_index_changed(self):
    index = self.comboBox.currentIndex()  # 获取当前索引
    # ... 使用索引执行操作 ...

# 连接信号和槽
comboBox.currentIndexChanged.connect(self.on_current_index_changed)

解决办法:必须在comboBox的currentIndexChanged事件响应函数commitData中传递一个int类型的入参,修改后的代码如下:

self.comboBox.currentIndexChanged.connect(
            lambda: self.commitData(self.comboBox.currentIndex())
        )

def commitData(self, commit_index):
     editor = self.sender()
     model = self.comboBox.model()

     # 找到当前编辑的单元格的索引
     for view in QApplication.instance().allWidgets():
         if isinstance(view, QTableView):
             for index in view.selectionModel().selectedIndexes():
                 if view.indexWidget(index) == editor:
                     commit_index = index
                     break

     # 提交数据到模型
     model.setData(commit_index, editor.currentText(), Qt.EditRole)

2.3 设置点击表格列标题后的列表框显示事件

    @Slot()
     def showFilterComboBox(self, column_index):
        # 先隐藏已经出现的筛选列表框
        self._hide_combox()
        # 在列标题旁边显示一个CustomComboBox
        combo = CustomComboBox(self)
        # 添加筛选选项
        column_data_lst = []
        for row in range(self.tableWidget.rowCount()):
            editor = self.tableWidget.cellWidget(row, column_index)
            if isinstance(editor, QComboBox):
                num_items = editor.count()
                # 迭代并打印每个选项的文本
                for i in range(num_items):
                    item_text = editor.itemText(i)
                    column_data_lst.append(item_text)
            else:
                item = self.tableWidget.item(row, column_index)
                if item is not None:
                    data = item.text()
                else:
                    data = ""
                column_data_lst.append(data)

        column_data_lst = sorted(set(column_data_lst))
        combo.addItems(column_data_lst)
        combo.activated.connect(
            lambda index: self.filterTableByColumn(column_index, combo.currentText())
        )

        # 计算显示位置
        # Get the position and size of the QTableWidget
        table_rect = self.tableWidget.geometry()
        header_height = self.tableWidget.horizontalHeader().height()

        # Calculate the position for the CustomComboBox
        column_width_sum = self._get_column_width_sum(column_index)
        combo_box_x = table_rect.x() + column_width_sum
        combo_box_y = (
            table_rect.y() + header_height
        )  # Position it right below the header

        # Set the geometry for the CustomComboBox
        combo_box_width = self.tableWidget.columnWidth(
            column_index
        )  # Match the column width
        combo_box_height = (
            combo.sizeHint().height()
        )  # Use the combo box's preferred height
        combo.setGeometry(combo_box_x, combo_box_y, combo_box_width, combo_box_height)
        combo.show()

        # 存储这个CustomComboBox以便后续处理(比如隐藏它)
        self.filter_comboboxes[column_index] = combo

2.4 计算ComboBox的显示位置

要想列表选择框显示在选中列的右侧,关键在于计算好ComboBox在界面上显示的位置

    # 计算显示位置
    # Get the position and size of the QTableWidget
    table_rect = self.tableWidget.geometry()
    header_height = self.tableWidget.horizontalHeader().height()

    # Calculate the position for the CustomComboBox
    column_width_sum = self._get_column_width_sum(column_index)
    combo_box_x = table_rect.x() + column_width_sum
    combo_box_y = (
        table_rect.y() + header_height
    )  # Position it right below the header

    # Set the geometry for the CustomComboBox
    combo_box_width = self.tableWidget.columnWidth(
        column_index
    )  # Match the column width
    combo_box_height = (
        combo.sizeHint().height()
    )  # Use the combo box's preferred height
    combo.setGeometry(combo_box_x, combo_box_y, combo_box_width, combo_box_height)
    combo.show()

2.5 根据列表框用户选中的数值显示表格内容

要想做到根据列表框用户选中的数值显示表格内容,关键在于显示和隐藏表格的行数据

@Slot()
def filterTableByColumn(self, column_index, value):
    # 根据列和值来筛选表格
    for row in range(self.tableWidget.rowCount()):
        item = self.tableWidget.item(row, column_index)
        if item is not None:
            data = item.text()
        else:
            data = ""
        if data == value:
            self.tableWidget.showRow(row)
        else:
            self.tableWidget.hideRow(row)
    # 隐藏列表框
    self.filter_comboboxes[column_index].hide()

http://www.kler.cn/a/452300.html

相关文章:

  • 每天40分玩转Django:Django静态文件
  • 【LuaFramework】服务器模块相关知识
  • 【R语言遥感技术】“R+遥感”的水环境综合评价方法
  • Nginx界的天花板-Oracle 中间件OHS 11g服务器环境搭建
  • SOTA简繁中文拼写检查工具:FASPell Chinese Spell Checker 论文
  • 强大且灵活的终端工具Tabby的强大功能与详细配置指南
  • 数据仓库是什么?数据仓库简介
  • 设计一个自己的AI Agent
  • .NET 9 中的 多级缓存 HybridCache
  • Android绘图Path基于LinearGradient线性动画渐变,Kotlin(2)
  • HarmonyOS NEXT 实战之元服务:静态案例效果---电台推荐
  • 【1224】数据结构(sizeof/数组的长度定义/读取字符串函数/线性表长度/左值右值/静态变量/指针与引用)
  • WPF自定义窗口 输入验证不生效
  • SpringBoot3-第四篇(基础特性)
  • Mybatisplus如何使用selectPage
  • 接口测试Day03-postman断言关联
  • HuaWei、NVIDIA 数据中心 AI 算力对比
  • 谈谈JSON
  • DigitalOcean Droplet 云服务器:新增自动扩展池功能
  • npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
  • openwrt 负载均衡方法 openwrt负载均衡本地源接口
  • 08 Django - Django媒体文件静态文件文件上传
  • Ubuntu存储硬盘扩容-无脑ChatGPT方法
  • 嵌入式学习-QT-Day06
  • 网站使用站群服务器都有哪些好处?
  • Vue学习手册03 Vue虚拟DOM详解