一、效果展示
二、实现思路
Qt自带的示例Frozen Column Exmaple实现冻结列的思路为用一个QTableView盖住另一个QTableView并只显示冻结的列,共用一个Model,该方法存在占用内存,若按其思路同时冻结行和列则需要创建行列各一个QTableView还有相交部分一个QTableView,而且同时滚动时不方便处理,也不能对数据进行编辑不能进行行宽列宽的调事等操作,在尝试后,放弃使用其实现方法。这里采用的冻结行和冻结列的思路为添加行列滚动条设置其parent为QTableView自带的滚动条,覆盖显示在滚动条上,并通过重写QTableView的resizeEvent来保证添加的滚动条始终覆盖QTableView自动的滚动条。冻结为设置QTableView自滚动条的value值为零,则始终会显示冻结列和冻结行,然后计算滚动时需要隐藏和显示的行和列,则只需要一个QTableView,这样可进行编辑、行宽、列宽等操作,占用内存也少。通过滚动条的actionTriggered(int action)信号对QTableView的item显示和隐藏进行控制,通过eventFilter处理QTableView的键盘箭头向上、箭头向下、箭头向左和箭头向右四个键按下事件,控制item的显示和隐藏。
三、核心代码
freezetableview.h
#ifndef FREEZETABLEVIEW_H
#define FREEZETABLEVIEW_H
#include <QTableView>
#include <QScrollBar>
#include <QMap>
class FreezeTableView : public QTableView
{
Q_OBJECT
public:
FreezeTableView(QWidget *parent = nullptr);
//冻结前几行
void freezeRow(int freezeRowNum);
//取消冻结前几行
void cancelFreezeRow();
//冻结结前几列
void freezeColumn(int freezeColumnNum);
//取消冻结前几列
void cancelFreeColumn();
//设置冻结的行列的背景色
void setFreezeBackgroundColor(QColor color);
protected:
void resizeEvent(QResizeEvent *event) override;
bool eventFilter(QObject* object,QEvent* event) override;
private:
//垂直滚动条
QScrollBar* m_vScrollBar;
//水平滚动条
QScrollBar* m_hScrollBar;
//冻结的行数
int m_freezeRowNum;
//冻结的列数
int m_freezeColumnNum;
//保存各行的显示隐藏状态
QMap<int,bool> m_rowVisibleMap;
//保存各列的显示隐藏状态
QMap<int,bool> m_columnVisibleMap;
//冻结颜色
QColor m_freezeBackgroundColor=Qt::gray;
//垂直滚动条当前值对应的行
int m_currentRow;
//水平滚动条当前值对应的列
int m_currentColumn;
//保存水平滚动条的值,用于判断拖动滑块时是左移还是右移
int m_hOldValue;
//保存垂直滚动条的值,用于判断拖动滑块时是上移还是下移
int m_vOldValue;
//重置各行的显示隐藏情况
void resetRowShowStatus();
//重围各列的显示隐藏情况
void resetColumnShowStatus();
//计算冻结行的高度
int getFreezeRowHeight();
//计算冻结列的高度
int getFreezeColumnWidth();
//向下滚动
void scrollDown(int step);
//向上滚动
void scrollUp(int step);
//向左滚动
void scrollLeft(int step);
//向右滚动
void scrollRight(int step);
//箭头向下处理函数
void moveDown();
//箭头向上处理函数
void moveUp();
//箭头向左处理函数
void moveLeft();
//箭头向右处理函数
void moveRight();
signals:
private slots:
//水平滚动条ActionTriggered处理槽函数
void hActionTriggered(int action);
//垂直滚动条ActionTriggered处理槽函数
void vActionTriggered(int action);
};
#endif // FREEZETABLEVIEW_H
freezetableview.cpp
#include "freezetableview.h"
#include<QHeaderView>
#include<QWheelEvent>
#include<QKeyEvent>
#include<QtMath>
#define BackupBackgroundColor Qt::UserRole+1
FreezeTableView::FreezeTableView(QWidget *parent) : QTableView(parent)
{
m_hScrollBar=new QScrollBar(Qt::Horizontal,horizontalScrollBar());
m_vScrollBar=new QScrollBar(Qt::Vertical,verticalScrollBar());
connect(m_hScrollBar,&QScrollBar::actionTriggered,this,&FreezeTableView::hActionTriggered);
connect(m_vScrollBar,&QScrollBar::actionTriggered,this,&FreezeTableView::vActionTriggered);
m_freezeRowNum=0;
m_freezeColumnNum=0;
m_currentRow=0;
m_currentColumn=0;
m_hOldValue=0;
m_vOldValue=