冻结表格列PyQt

2023-11-08

QT有个官方的例子:Frozen Column Example,在Qt Creator例子查找即可

官方例子python版本:

Frozen Column Example - Qt for Python

不过官方python版应该是机器直接翻译的C++版的,代码都不正常

根据C++和python版,自己实现了python版的,完善部分功能

import sys

from PyQt5.QtWidgets import QApplication, QHeaderView, QTableView, QAbstractItemView, QScrollBar, QFrame
from PyQt5.QtCore import Qt
# from PyQt5.QtCore import Signal, Slot
# from PyQt5.QtCore import SIGNAL, SLOT
from PyQt5.QtGui import QStandardItemModel, QStandardItem


class FreezeTableWidget(QTableView):
    """
    冻结部分列类

    参照例程 frozencolumn 实现,
    https://doc.qt.io/qtforpython/overviews/qtwidgets-itemviews-frozencolumn-example.html?highlight=frozen
    中也包含部分修改后的python代码,似乎不完整
    """

    def __init__(self, parent=None):
        super(FreezeTableWidget, self).__init__()

        # 创建一个QTableView子控件
        self.frozenTableView = QTableView(self)
        self.frozenColumnCount = 1  # 冻结列数,冻结前几列

        # connect the headers and scrollbars of both tableviews together
        # self.connect(self.horizontalHeader(), SIGNAL('sectionResized(int,int,int)'), self, SLOT('updateSectionWidth(int,int,int)'))
        self.horizontalHeader().sectionResized.connect(self.updateSectionWidth)
        # self.connect(self.verticalHeader(), SIGNAL('sectionResized(int,int,int)'), self, SLOT('updateSectionHeight(int,int,int)'))
        self.verticalHeader().sectionResized.connect(self.updateSectionHeight)

        # self.connect(self.frozenTableView.horizontalHeader(), SIGNAL('sectionResized(int,int,int)'), self, SLOT('frozenTableHeaderSectionResized(int,int,int)'))
        self.frozenTableView.horizontalHeader().sectionResized.connect(self.frozenTableHeaderSectionResized)

        # self.connect(self.frozenTableView.verticalScrollBar(), SIGNAL('valueChanged(int)'), self.verticalScrollBar(), SLOT('setValue(int)'))
        self.frozenTableView.verticalScrollBar().valueChanged.connect(self.verticalScrollBar().setValue)
        # self.connect(self.verticalScrollBar(), SIGNAL('valueChanged(int)'), self.frozenTableView.verticalScrollBar(), SLOT('setValue(int)'))
        self.verticalScrollBar().valueChanged.connect(self.frozenTableView.verticalScrollBar().setValue)

    def initFrozenTableView(self):
        """
        初始化 frozenTableView 表格对象
        :return:
        """
        if self.model() is None:
            return
        self.frozenTableView.setModel(self.model())
        # self.frozenTableView.setFocusPolicy(Qt.NoFocus)
        self.frozenTableView.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        self.frozenTableView.verticalHeader().hide()
        # self.frozenTableView.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed) # 设置表头固定大小

        self.viewport().stackUnder(self.frozenTableView)

        # 设置无边框
        # self.frozenTableView.setFrameShape(QFrame.NoFrame)
        # self.frozenTableView.setFrameStyle(QFrame.NoFrame | QFrame.Plain)
        self.frozenTableView.setFrameStyle(QFrame.Shape.NoFrame | QFrame.Shadow.Plain)
        # self.frozenTableView.setStyleSheet("QTableView { border: none;background-color: #8EDE21;selection-background-color: #999}")  # 设置无边框和背景色
        # self.frozenTableView.setStyleSheet("QTableView { border: none;}")   # 设置无边框

        self.frozenTableView.setSelectionModel(self.selectionModel())  # 设置相同的选择模式

        for col in range(self.model().columnCount()):
            # frozenTableView隐藏不冻结列
            self.frozenTableView.setColumnHidden(col, True if col >= self.frozenColumnCount else False)
            # frozenTableView冻结列设置宽度等于主表格
            self.frozenTableView.setColumnWidth(col, self.columnWidth(col))

        # 不显示滚动条
        self.frozenTableView.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.frozenTableView.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.frozenTableView.show()

        self.updateFrozenTableGeometry()

        self.setHorizontalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
        self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
        self.frozenTableView.setHorizontalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
        self.frozenTableView.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)

    def setFrozenColumnCount(self, frozenColumnCount: int):
        """
        设置冻结列数
        :param frozenColumnCount:
        :return:
        """
        self.frozenColumnCount = frozenColumnCount
        self.initFrozenTableView()  # 重新初始化 frozenTableView

    # 重载父类函数
    def setModel(self, model):
        """
        设置数据模型
        :param model:
        :return:
        """
        super().setModel(model)
        self.initFrozenTableView()  # 重新初始化 frozenTableView
        # 连接信号,在列改变时重新设置 frozenTableView 的列显示隐藏
        model.columnsInserted.connect(self.columnsInserted)

    def setSortingEnabled(self, enable):
        """
        设置是否支持排序
        :param enable:
        :return:
        """
        super().setSortingEnabled(enable)
        self.frozenTableView.setSortingEnabled(enable)

    # @Slot()
    def updateSectionWidth(self, logicalIndex, oldSize, newSize):
        """
        更新冻结table的列宽
        :param logicalIndex:
        :param oldSize:
        :param newSize:
        :return:
        """
        if logicalIndex < self.frozenColumnCount:
            self.frozenTableView.setColumnWidth(logicalIndex, newSize)
            self.updateFrozenTableGeometry()

    # @Slot()
    def updateSectionHeight(self, logicalIndex, oldSize, newSize):
        """
        更新冻结table的行高
        :param logicalIndex:
        :param oldSize:
        :param newSize:
        :return:
        """
        self.frozenTableView.setRowHeight(logicalIndex, newSize)

    # @Slot()
    def frozenTableHeaderSectionResized(self, logicalIndex, oldSize, newSize):
        """
        冻结列表格大小改变,同时修改主表格相应列宽
        :param logicalIndex:
        :param oldSize:
        :param newSize:
        :return:
        """
        # print("frozenTableHeaderSectionResized({},{},{})".format(logicalIndex, oldSize, newSize))
        if logicalIndex < self.frozenColumnCount:
            self.setColumnWidth(logicalIndex, newSize)

    def resizeEvent(self, event):
        """
        重载父类函数
        :param event:
        :return:
        """
        super().resizeEvent(event)
        self.updateFrozenTableGeometry()

    def moveCursor(self, cursorAction, modifiers):
        """
        重载父类函数
        :param cursorAction:
        :param modifiers:
        :return:
        """
        # print("moveCursor({}, {})".format(cursorAction, modifiers))
        current = super().moveCursor(cursorAction, modifiers)
        # 游标左移时避免 frozenTableView 遮住当前选择的项
        if cursorAction == QAbstractItemView.CursorAction.MoveLeft \
                and current.column() >= self.frozenColumnCount \
                and self.visualRect(current).topLeft().x() < self.frozenTableView.width():
            newValue = self.horizontalScrollBar().value() + self.visualRect(
                current).topLeft().x() - self.frozenTableView.width()
            self.horizontalScrollBar().setValue(newValue)

        # 右移、上下移动游标时,避免 frozenTableView 遮住当前选择的项
        if ((cursorAction == QAbstractItemView.CursorAction.MoveRight
             or cursorAction == QAbstractItemView.CursorAction.MoveUp
             or cursorAction == QAbstractItemView.CursorAction.MoveDown
             or cursorAction == QAbstractItemView.CursorAction.MovePageUp
             or cursorAction == QAbstractItemView.CursorAction.MovePageDown
             or cursorAction == QAbstractItemView.CursorAction.MoveNext
             or cursorAction == QAbstractItemView.CursorAction.MovePrevious)
                and self.visualRect(current).topLeft().x() < self.frozenTableView.width()):
            newValue = self.horizontalScrollBar().value() + self.visualRect(
                current).topLeft().x() - self.frozenTableView.width()
            self.horizontalScrollBar().setValue(newValue)

        return current

    def scrollTo(self, index, hint):
        """
        重载父类函数
        :param index:
        :param hint:
        :return:
        """
        # print("scrollTo({}, {})".format(index, hint))
        if index.column() >= self.frozenColumnCount:
            super().scrollTo(index, hint)

    def updateFrozenTableGeometry(self):
        """
        更新冻结表格Geometry
        :return:
        """
        x = self.verticalHeader().width() + self.frameWidth()
        y = self.frameWidth()
        w = 0  # self.columnWidth(0)
        for col in range(0, self.frozenColumnCount):
            w += self.columnWidth(col)
        h = self.viewport().height() + self.horizontalHeader().height()
        # 设置新位置和宽高
        self.frozenTableView.setGeometry(x, y, w, h)

    # @Slot()
    def columnsInserted(self, parent, first, last):
        """
        在列改变时重新设置 frozenTableView 的列显示隐藏
        :param parent:
        :param first:
        :param last:
        :return:
        """
        # print("columnsInserted({},{},{})".format(parent, first, last))
        for col in range(self.model().columnCount()):
            # frozenTableView隐藏不冻结列
            self.frozenTableView.setColumnHidden(col, True if col >= self.frozenColumnCount else False)
            # frozenTableView冻结列设置宽度等于主表格
            self.frozenTableView.setColumnWidth(col, self.columnWidth(col))


if __name__ == '__main__':
    def test():
        # 测试例子
        app = QApplication(sys.argv)

        model = QStandardItemModel()
        horizontalHeaderLabel = []
        for col in range(20):
            horizontalHeaderLabel.append("列{}".format(col))
        model.setHorizontalHeaderLabels(horizontalHeaderLabel)
        for col in range(len(horizontalHeaderLabel)):
            for row in range(50):
                # if col != 4:
                model.setItem(row, col, QStandardItem('{},{}'.format(row, col)))
                # else:
                #    model.setItem(row, col, QStandardItem('{},{}XXXXXXXXXXXXXXXX'.format(row, col)))

        tableView = FreezeTableWidget()
        tableView.setWindowTitle("Frozen Column Example")
        tableView.resize(560, 680)
        tableView.setSortingEnabled(True)

        tableView.setFrozenColumnCount(2)
        tableView.setModel(model)

        tableView.show()

        sys.exit(app.exec())


    # 调用测试例子
    test()

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

冻结表格列PyQt 的相关文章

随机推荐

  • android--emo的来源

    文章目录 前言 第一次安装 bug出现了 idea配置android开发环境 碰运气 重新下载 导入项目 测试成功 感悟 前言 记录一下我安装android studio的心路历程 为什么就我遇到这么多问题 第一次安装 这学期新开的移动应用
  • python选择与循环结构之判断三角形:任意输入三个整数作为三角形边长,判断三条边能否构成三角形,并判断是等边三角形、等腰三角形,直角三角形,还是一般三角形。

    问题描述 任意输入三个整数作为三角形边长 判断三条边能否构成三角形 并判断是等边三角形 等腰三角形 直角三角形 还是一般三角形 实现代码如下 a int input 请输入a b int input 请输入b c int input 请输入
  • Winsock Error Codes

    Winsock Error Codes 10004 WSAEINTRInterrupted function call This error indicates that a blocking call was interrupted by
  • JavaScript 严格模式(use strict)

    JavaScript严格模式 又称为 use strict 模式 是JavaScript语言的一种更严格的运行模式 严格模式规定了一些限制 用于防止程序员犯一些常见的错误 以保证代码的正确性和安全性 在JavaScript严格模式中 不允许
  • 刷脸支付智慧经营创业红利赢在坚持不懈

    这是一个最好的时代 我们身处繁华的都市 有着一个体面稳定的工作 科技日新月异 生活便捷高效 这是一个最坏的时代 房价水涨船高 工资涨幅完全跟不上物价的涨幅 8090后年轻人们面临着巨大的生活压力 钱 成为了禁锢他们的牢笼 在这个时代 普通人
  • Mybatis如何处理Result Maps collection already contains value for xxx异常呢?

    转自 Mybatis如何处理Result Maps collection already contains value for xxx异常呢 下文笔者讲述一次mybatis异常的处理分享 如下所示 Mybatis异常摘要 2022 08 1
  • Java初识RabbitMQ一交换机(fanout exchange)

    扇型交换机 funout exchange 将消息路由给绑定到它身上的所有队列 而不理会绑定的路由键 如果 N 个队列绑定到某个扇型交换机上 当有消息发送给此扇型交换机时 交换机会将消息的拷贝分别发送给这所有的 N 个队列 因为扇型交换机投
  • 取消已设置为SVN的文件夹(清理SVN标志)

    取消CheckOut后的文件与svn的联系 Windows Registry Editor Version 5 00 HKEY LOCAL MACHINE SOFTWARE Classes Folder shell DeleteSVN 删除
  • 代码随想录训练营第14天

    参考 代码随想录 一 理论基础 一 二叉树的种类 满二叉树 完全二叉树 二叉搜索树 平衡二叉搜索树 二 二叉树的存储方式 顺序存储 顺序存储的元素在内存中是连续分布的 通常用数组来存储 如果父节点的数组下标是 i 那么它的左孩子就是 i 2
  • ucos学习资料、论坛等

    论坛 http bbs elecfans com forum php mod forumdisplay fid 301 typeid 505 教程推荐 第一步 嵌入式实时操作系统 COS II原理及应用 任哲编著 首选任哲的这本书 我建议先
  • 对IOC和DI的通俗理解

    学习过spring框架的人一定都会听过Spring的IoC 控制反转 DI 依赖注入 这两个概念 对于初学Spring的人来说 总觉得IoC DI这两个概念是模糊不清的 是很难理解的 今天和大家分享网上的一些技术大牛们对Spring框架的I
  • Flink ML API,为实时机器学习设计的算法接口与迭代引擎

    摘要 本文整理自阿里巴巴高级技术专家林东 阿里巴巴技术专家高赟 云骞 在 Flink Forward Asia 2021 核心技术专场的演讲 主要内容包括 面向实时机器学习的 API 流批一体的迭代引擎 Flink ML 生态建设 一 面向
  • Linux下快速查看CPU使用情况的相关命令

    Linux下快速查看CPU使用情况比较常用的命令是free top ps 这篇文章来看下如何在Linux下检查服务器的CPU使用情况 我的Linux是Linux Ubuntu server 15 04 如果是图形界面 有些统计会看起来更直观
  • Intellij Idea创建一个简单的java项目

    2016年11月12日 我即将要离开象牙塔 校园 踏入社会 想想未来我是某个公司的一个程序员 再对比一下小时的梦想 好像出入挺大的 今天我不得不为即将的工作准备 一个java开发工程师 但是我现在是一个小小的菜鸟 所以要学习 好了 不说这些
  • 简单说说对QT中moveToThread实现多线程操作的理解

    在平时的编码过程中经常碰到QT的多线程问题 也大量接触了QT中的两种主流多线程写法 一种是继承QThread类并重载run函数 在run函数中写一个状态机或者计时器来实现对线程运作 一种是通过moveToThread的方式实现事件托管从而实
  • nginx在Linux上搭建

    一 Nginx介绍和常用功能 1 Nginx介绍 Nginx是一个高性能的HTTP和反向代理 服务器 百度百科的介绍 常见功能 Http代理 反向代理 作为web服务器最常用的功能之一 尤其是反向代理 正向代理和反向代理不理解的可以看htt
  • 轮播图插件使用

    React使用最广泛的轮播图插件之一是 react slick react slick 是一个基于React的响应式轮播图组件 具有许多可定制的选项和功能 要使用 react slick 插件 您可以按照以下步骤进行 1 安装 react
  • 华为数据中心产品汇总介绍

    AR G3路由器产品定位 AR G3系列企业路由器是秉承华为在数据通信 无线 接入网 核心网领域的深厚积累 依托自主知识产权的VRP平台 通用路由平台 主要是以TCP IP协议为核心 实现了数据链路层 网络层和应用层的多种协议 推出的面向企
  • yagmail发送带图片和链接的邮件

    方法 在正文中插入图片 yagmail inlne 图片路径 在正文中插入链接 a href 链接地址 链接名称 a 效果如图 经过测试的完整代码 导入yagmail第三方库 import yagmail yagmail SMTP user
  • 冻结表格列PyQt

    QT有个官方的例子 Frozen Column Example 在Qt Creator例子查找即可 官方例子python版本 Frozen Column Example Qt for Python 不过官方python版应该是机器直接翻译的