Qt编程-QTableView冻结行或冻结列或冻结局部单元格

news2024/11/19 12:38:11

前言

Qt编程-QTableView冻结行或冻结列或冻结局部单元格。如题,先看效果是不是你需要的。网上找到的代码片段要么不全要么不是想要的。如果你需要同时冻结行和列的效果,请看下篇博客 Qt编程-QTableView同时冻结行和列。

冻结列:
在这里插入图片描述

冻结行:
在这里插入图片描述

冻结局部单元格:
在这里插入图片描述

原理

冻结行或者冻结列原理: 使用2个tableview ,内容一样,上层tableview显示冻结的行或列 把非冻结的内容隐藏掉,下层tableview显示全部内容 下层tableview正常滑动就有冻结行或者列的效果了。

代码

代码改造来自 Qt自带例子 。可通过宏变量FREEZE_COL和FREEZE_ROW控制冻结行或冻结列。完整工程代码下载。

主要代码如下:

freezetablewidget.h

#ifndef FREEZETABLEWIDGET_H
#define FREEZETABLEWIDGET_H

#include <QTableView>

//! [Widget definition]
class FreezeTableWidget : public QTableView {
     Q_OBJECT

public:
      FreezeTableWidget(QAbstractItemModel * model);
      ~FreezeTableWidget();


protected:
      void resizeEvent(QResizeEvent *event) override;
      QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override;
      void scrollTo (const QModelIndex & index, ScrollHint hint = EnsureVisible) override;

private:
      QTableView *frozenTableView;
      void init();
      void updateFrozenTableGeometry();


private slots:
      void updateSectionWidth(int logicalIndex, int oldSize, int newSize);
      void updateSectionHeight(int logicalIndex, int oldSize, int newSize);
private:
      //冻结的行列数
      int m_iFreezeCols = 3;
      int m_iFreezeRows = 3;
};
//! [Widget definition]
#endif // FREEZETABLEWIDGET_H

freezetablewidget.cpp

#include "freezetablewidget.h"

#include <QScrollBar>
#include <QHeaderView>
#include <QDebug>

#define FREEZE_COL 1 //冻结列开关
#define FREEZE_ROW 1 //冻结行开关

//! [constructor]
FreezeTableWidget::FreezeTableWidget(QAbstractItemModel * model)
{
      /*
冻结行或者冻结列原理:
实质上有2个tableview
            FreezeTableWidget继承QTableView 这个正常显示所有的表格数据
            FreezeTableWidget的成员变量frozenTableView 这个表格放在FreezeTableWidget的上面 只显示 冻结的行或者列 或者 你想显示的单元格,这样下面的 FreezeTableWidget 正常滑动就有冻结行或者列的效果了。
     */
      setModel(model);
      frozenTableView = new QTableView(this);

      init();

      //connect the headers and scrollbars of both tableviews together
      connect(horizontalHeader(),&QHeaderView::sectionResized, this,
              &FreezeTableWidget::updateSectionWidth);
      connect(verticalHeader(),&QHeaderView::sectionResized, this,
              &FreezeTableWidget::updateSectionHeight);

      //LUpdate
      //冻结列,纵向滚动条可正常滑动
#if (FREEZE_COL && !FREEZE_ROW)
      connect(frozenTableView->verticalScrollBar(), &QAbstractSlider::valueChanged,
              verticalScrollBar(), &QAbstractSlider::setValue);
      connect(verticalScrollBar(), &QAbstractSlider::valueChanged,
              frozenTableView->verticalScrollBar(), &QAbstractSlider::setValue);
#endif
      //冻结行,横向滚动条可正常滑动
#if (!FREEZE_COL && FREEZE_ROW)
      connect(frozenTableView->horizontalScrollBar(), &QAbstractSlider::valueChanged,
              horizontalScrollBar(), &QAbstractSlider::setValue);
      connect(horizontalScrollBar(), &QAbstractSlider::valueChanged,
              frozenTableView->horizontalScrollBar(), &QAbstractSlider::setValue);
#endif
}
//! [constructor]

FreezeTableWidget::~FreezeTableWidget()
{
      delete frozenTableView;
}

//! [init part1]
void FreezeTableWidget::init()
{
      frozenTableView->setModel(model());
      frozenTableView->setFocusPolicy(Qt::NoFocus);
      frozenTableView->verticalHeader()->setFixedWidth(verticalHeader()->width());
      frozenTableView->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
      frozenTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);

      viewport()->stackUnder(frozenTableView);
//! [init part1]

//! [init part2]
      frozenTableView->setStyleSheet("QTableView { border: none;"
                                     "background-color: #8EDE21;"
                                     "selection-background-color: #999}"); //for demo purposes
      frozenTableView->setSelectionModel(selectionModel());
      
      //LUpdate
#if FREEZE_COL
      //隐藏冻结列以外的数据
      for (int col = m_iFreezeCols; col < model()->columnCount(); ++col)
          frozenTableView->setColumnHidden(col, true);

      for(int i = 0; i < m_iFreezeCols; i++)
      {
          frozenTableView->setColumnWidth(i, columnWidth(0));
      }
#endif

#if FREEZE_ROW
      //隐藏冻结行以外的行的数据
      for (int row = m_iFreezeRows; row < model()->rowCount(); ++row)
          frozenTableView->setRowHidden(row, true);
      for(int i = 0; i < m_iFreezeRows; i++)
      {
          frozenTableView->setRowHeight(i, rowHeight(0));
      }
#endif


      frozenTableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
      frozenTableView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
      frozenTableView->show();

      updateFrozenTableGeometry();

      setHorizontalScrollMode(ScrollPerPixel);
      setVerticalScrollMode(ScrollPerPixel);
      frozenTableView->setVerticalScrollMode(ScrollPerPixel);
      frozenTableView->setHorizontalScrollMode(ScrollPerPixel);
}
//! [init part2]


//! [sections]
void FreezeTableWidget::updateSectionWidth(int logicalIndex, int /* oldSize */, int newSize)
{
    qDebug() << "updateSectionWidth" << logicalIndex << newSize;
    //LUpdate
#if FREEZE_COL
    if (logicalIndex == m_iFreezeCols-1){

        int width = 0;
        for(int i = 0; i< m_iFreezeCols-1; i++)
        {
            width += columnWidth(i);
        }

        for(int i = 0; i< m_iFreezeCols; i++)
        {
            frozenTableView->setColumnWidth(i, (newSize+width)/m_iFreezeCols);
        }
        updateFrozenTableGeometry();
    }
#else
    frozenTableView->setColumnWidth(logicalIndex, newSize);
#endif
}

void FreezeTableWidget::updateSectionHeight(int logicalIndex, int /* oldSize */, int newSize)
{
    qDebug() << "updateSectionHeight" << logicalIndex << newSize;
    //LUpdate
#if FREEZE_ROW
    if (logicalIndex == m_iFreezeRows-1){

        int height = 0;
        for(int i = 0; i< m_iFreezeRows-1; i++)
        {
            height += rowHeight(i);
        }

        for(int i = 0; i< m_iFreezeRows; i++)
        {
            frozenTableView->setRowHeight(i, (newSize+height)/m_iFreezeRows);
        }
        updateFrozenTableGeometry();
    }
#else
    frozenTableView->setRowHeight(logicalIndex, newSize);
#endif
}
//! [sections]


//! [resize]
void FreezeTableWidget::resizeEvent(QResizeEvent * event)
{
      QTableView::resizeEvent(event);
      updateFrozenTableGeometry();
 }
//! [resize]


//! [navigate]
QModelIndex FreezeTableWidget::moveCursor(CursorAction cursorAction,
                                          Qt::KeyboardModifiers modifiers)
{
      QModelIndex current = QTableView::moveCursor(cursorAction, modifiers);

#if FREEZE_COL
      if (cursorAction == MoveLeft && current.column() > 0
              && visualRect(current).topLeft().x() < frozenTableView->columnWidth(0) ){
            const int newValue = horizontalScrollBar()->value() + visualRect(current).topLeft().x()
                                 - frozenTableView->columnWidth(0);
            horizontalScrollBar()->setValue(newValue);
      }
#endif
#if FREEZE_ROW
      if(cursorAction == MoveDown && current.row() > 0
              && visualRect(current).topLeft().y() < frozenTableView->rowHeight(0))
      {
          const int newValue = verticalScrollBar()->value() + visualRect(current).topLeft().y()
                               - frozenTableView->rowHeight(0);
          verticalScrollBar()->setValue(newValue);
      }
#endif
      return current;
}
//! [navigate]

void FreezeTableWidget::scrollTo (const QModelIndex & index, ScrollHint hint){
    if (index.column() > 0)
        QTableView::scrollTo(index, hint);
}

//! [geometry]
void FreezeTableWidget::updateFrozenTableGeometry()
{
    //LUpdate
    int width = 0, height = 0, x = 0, y = 0;
    qDebug() << "ver:" << verticalHeader()->width() << verticalHeader()->height();
    qDebug() << "hor:" << horizontalHeader()->width() << horizontalHeader()->height();
    qDebug() << "frame:" << frameWidth() << frameRect().width()<< frameRect().height() << frameRect().x() << frameRect().y();
    x = frameWidth();
    y = frameWidth();

#if FREEZE_COL
    width = verticalHeader()->width();
    for(int i = 0; i< m_iFreezeCols; i++)
    {
       width += columnWidth(i);
    }
#else
    width = viewport()->width()+verticalHeader()->width();
#endif

#if FREEZE_ROW
    height = horizontalHeader()->height();
    for(int i = 0; i< m_iFreezeRows; i++)
    {
       height += rowHeight(i);
    }
#else
    height = viewport()->height()+horizontalHeader()->height();
#endif

    qDebug() << "x, y, width, height" << x << y << width << height;
    frozenTableView->setGeometry(x, y, width, height);
}
//! [geometry]



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1076138.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[stm32]外中断控制灯光

在STM32CubeMX中配置外部中断功能和参数 1、将上拉输入的引脚设置为&#xff1a;GPIO_EXTI功能 2、GPIO模式设为下降沿触发外部中断&#xff0c;使能上拉电阻&#xff0c;用户标签 3、要将NVIC的相关中断勾选 只有将中断源进行勾选&#xff0c;相关的中断请求才能得到内核的…

华为云云耀云服务器L实例评测|企业项目最佳实践之云服务器介绍(一)

华为云云耀云服务器L实例评测&#xff5c;企业项目最佳实践系列&#xff1a; 华为云云耀云服务器L实例评测&#xff5c;企业项目最佳实践之云服务器介绍(一) 华为云云耀云服务器L实例评测&#xff5c;企业项目最佳实践之华为云介绍(二) 华为云云耀云服务器L实例评测&#xff5…

Hudi第三章:集成Flink

系列文章目录 Hudi第一章&#xff1a;编译安装 Hudi第二章&#xff1a;集成Spark Hudi第二章&#xff1a;集成Spark(二) Hudi第三章&#xff1a;集成Flink 文章目录 系列文章目录前言一、环境准备1.上传并解压2.修改配置文件3.拷贝jar包4.启动sql-client1.启动hadoop2.启动ses…

2023年中国助消化药物行业现状分析:消化不良患者逐年上升,提升需求量[图]

助消化药物主要分为促胃动力药物、消化酶抑制剂、胃酸抑制药物和消食剂4种类型。促胃动力药物的作用机制是通过增强胃肠道平滑肌动力促进胃酸分泌&#xff0c;从而达到助消化的目的&#xff0c;临床常用药物包括多潘立酮、莫沙必利、西沙比利等。 助消化药物分类 资料来源&…

SI314兼容替代 GTX314L—低功耗14通道电容触摸传感器芯片 应用智能门锁

1.介绍 Si314是一款具有自动灵敏度校准功能的14通道电容传感器&#xff0c;其工作电压范围为1.8~5.5v.Si314设置休眠模式来节省功耗&#xff0c;此时&#xff0c;功耗电流为10uA3. 3V。 Si314各个感应通道可实现独立使能、校准、灵敏度调节&#xff0c;可以确保可靠性&#x…

一款好用的PDF文档解密软件

PDF Decrypter pro 纯免费&#xff0c;没有页数限制&#xff0c;没有额外水印&#xff0c;强烈推荐&#xff01;

使用docker创建redis实例、主从复制、哨兵集群

单机模式 1 拉取镜像 docker pull redis:7.2.1 2 新建redis映射配置文件夹data和conf $ mkdir -p /mydata/redis/data $ mkdir -p /mydata/redis/conf 3 切换到redis配置文件映射目录/mydata/redis/conf cd /mydata/redis/conf 4 编辑配置文件 vim redis.…

算法题:单调递增的数字(贪心算法解决序列问题)

这道题参考了一位网友的思路&#xff0c;采用了贪心算法动态规划&#xff0c;具体思路如下&#xff1a;&#xff08;完整题目附在了最后面&#xff09; 1、从高到低遍历数字的每个位数&#xff0c;找到第一个数值递减&#xff08;<&#xff09;的地方&#xff0c;把当前位-…

[spring] spring jpa - hibernate 名词解释配置

[spring] spring jpa - hibernate 名词解释&配置 之前过了一遍依赖注入的内容&#xff0c;这次过一下数据相关的部分&#xff0c;完成了这部分内容&#xff0c;下篇就涉及到 API 实现了 操作的部分放到下一篇&#xff0c;本篇主要是概念配置 整体课程上来说&#xff0c;…

c++ pthread库使用

c pthread库使用 1. pthread库安装2. 测试demo3. 配置include/lib路径3.1 添加include路径3.2 配置lib文件路径 4.显示结果5. 遇到的bug参考文献 1. pthread库安装 打开ftp://sourceware.org/pub/pthreads-win32&#xff0c;下载一个安装包&#xff0c;如pthreads-w32-2-8-0-r…

STM32 CubeMX PWM三种模式(HAL库)

STM32 CubeMX PWM两种模式&#xff08;HAL库&#xff09; STM32 CubeMX STM32 CubeMX PWM两种模式&#xff08;HAL库&#xff09;一、互补对称输出STM32 CubeMX设置代码部分 二、带死区互补模式STM32 CubeMX设置代码 三、普通模式STM32 CubeMX设置代码部分 总结 一、互补对称输…

实现Java基于类的代理方式 - CGLIB动态代理(动态代理篇 三)

CGLIB&#xff08;Code Generation Library&#xff09;是一个基于类的动态代理库&#xff0c;它可以在运行时生成字节码来创建代理类。相比于JDK动态代理&#xff0c;CGLIB动态代理不需要接口&#xff0c;可以代理任意类。 CGLIB动态代理的实现原理是通过继承目标类来创建代理…

什么是网络流量监控

随着许多服务迁移到云&#xff0c;网络基础架构的维护变得复杂。虽然云采用在生产力方面是有利的&#xff0c;但它也可能让位于未经授权的访问&#xff0c;使 IT 系统容易受到安全攻击。 为了确保其网络的安全性和平稳的性能&#xff0c;IT 管理员需要监控用户访问的每个链接以…

【C++杂货铺】一文带你走进RBTree

文章目录 一、红黑树的概念二、红黑树的性质三、红黑树结点的定义四、红黑树的插入操作4.1 情况一&#xff1a;uncle 存在且为红4.2 情况二&#xff1a;uncle 不存在4.3 情况三&#xff1a;uncle 存在且为黑4.4 插入完整源码 五、红黑树的验证六、红黑树与 AVL 树的比较七、结语…

可替代allegroA3909的国产芯片GC3909的数据分析

GLOBALCHIP的 GC3909 是一款双通道 12V 直流电机驱动芯片&#xff0c;为摄像机、消费类产品、玩具和其他低压或 者电池供电的运动控制类应用提供了集成的电机驱动解决方案。芯片一般用来驱动两个直流电机 或者驱动一个步进电机。 而GC3909 可以工作在 3.8~12V 的电源电压上&…

Ant Design+react 路由跳转

今天我们来继续探讨react的路由跳转 首先&#xff0c;创建router文件夹中的index import { lazy } from "react"; import { Outlet,useRoutes } from react-router-dom; //引入页面&#xff0c;引用了路由懒加载 const One lazy(() > import(../pages/one)); c…

QT作业二

1、思维导图 https://www.zhixi.com/view/9e899ee0 2、作业 #include <iostream>using namespace std;class Rect {int width;int height; public:void init(int w,int h);//初始化函数void set_w(int w);//更改宽度void set_h(int h);//更改高度void show();//输出矩形…

DEDECMS织梦保存当前栏目更改时失败的解决方法

织梦编辑栏目时提示“保存当前栏目更改时失败&#xff0c;请检查你的输入资料是否存在问题&#xff01;” 那是因为你的后台栏目编辑文件php里有做过二次开发&#xff0c;添加了栏目数据表里不存在的字段。 跟着下面的步骤&#xff0c;让程序告诉你缺少什么引起的保存失败吧。 …

轻松玩转直播带货,铭顺科技揭秘数字人跳舞直播软件亮点

直播带货在商业领域越来越受追捧&#xff0c;而数字人直播作为一种创新推广方式&#xff0c;正逐渐引起关注。在这个竞争激烈的直播行业中&#xff0c;数字人私有化部署解决方案以其独特的优势和亮点&#xff0c;为用户提供了一个轻松玩转直播带货的利器。 数字人私有化部署解决…

leetCode 167.两数之和 || - 输入有序数组 双指针解法

167. 两数之和 II - 输入有序数组 - 力扣&#xff08;LeetCode&#xff09; 给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] …