原文链接:QRowTable表格控件-支持hover整行、checked整行、局部列排序等

一、开心一刻

老公和老婆晚上回家,路旁突然跳出三个持刀蒙面大汉:“绑架!你俩可以走一个,回家等消息。”

老公一把将老婆推开:“老婆快走!”待老婆走远后,三个蒙面人摘下面具:“尼玛现在找你打个麻将这么费劲?”

五分钟后老公致电老婆:"往卡里打五千块,别报警,他们说关我一夜明早放人。"十分钟后老公从卡里取走五千块战斗到天明。

次日老公回家,老婆扑上来含泪说:“关键时候才能看出老公对我的好,老公以后我啥都听你的!

二、嘴一嘴

看完笑话,我们进入正题。

本篇文章我们带来的是一个表格的简单使用,主要是把表格的hover、checked进行了重新定制,支持用户自己去设置相关颜色,并且可以对指定列进行放大缩小等。

为什么会写这篇文章呢?博主自己使用Qt也好几年了,对于Qt的使用算是比较有心得了吧。最近在做表格的一些相关东西,发现网上的很多文章讲的不是特别好,因此将自己做的一个简单事例做一分享,希望能帮到有需要的同学。

本篇文章我们主要对表格的以下内容进行了封装,内容比较有限,有深度定制需求的同学可以加我QQ详谈。

  1. hover行背景色
  2. checked行背景色
  3. 列宽是否可排序
  4. 列宽允许拖动范围
  5. 准确定位hover状态

三、效果展示

如下图所示,一个简单的gif效果展示。

配色时博主自己随便搞的,配色只能说很一般,大家主要看效果和实现思路。

四、浅谈实现

使用过QTableView或者了解控件的同学应该都很清楚,表格是一个很强大的控件,支持我们做各种各样的功能,博主之前也想过几篇相关的文章,都是讲述表格控件的。

  1. Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等

  2. Qt高仿Excel表格组件-支持冻结列、冻结行、内容自适应和合并单元格

  3. 属性浏览器控件QtTreePropertyBrowser编译成动态库(设计师插件)

  4. 超级实用的属性浏览器控件--QtTreePropertyBrowser

  5. Qt之表格控件蚂蚁线

当然了表格控件的使用远远不止于此,后续有时间和精力我会陆续推出更多有用好玩儿的功能。

本篇文章的功能实现也比较简单,写这个demo我大概用了大半天的时间,代码量其实不多,大部分的时间主要用来设计接口和重构逻辑功能了。

如下图所示,是整个工程目录结构,这里主要重写了数据源model和view

下面我们就分别讲述model和view都干了些什么

五、自定义数据源

所谓数据源,其实主要就是给view提供数据的地方,这里我们取了一个巧,数据源直接继承自QStandarItemModel,这样的话数据的存储和获取大部分的工作都不需要我们去关心,因为QStandarItemModel这个类已经做的很完善。

这里我们主要从写了两个接口

virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

virtual Qt::ItemFlags flags(const QModelIndex & index) const override;

1、data函数

视图获取数据的接口就是data,因此这个接口我们必须重写,实现代码也很简单,主要是需要大家对Qt的MVC有一个基本的认识。

QVariant QRowModel::data(const QModelIndex & index, int role /*= Qt::DisplayRole*/) const
{
if (Qt::BackgroundRole == role)
{
if (index.row() == m_iHoverRow)
{
return m_HoverColor;
}
}
else if (role == Qt::ForegroundRole)
{
if (index.row() == m_iHoverRow)
{
return m_HoverColor.lighter(255);
}
} return QStandardItemModel::data(index, role);
}

看上述代码,当绘制视图的时候,hover一行时,我们需要返回自定义的颜色值,其他情况走默认处理即可,是不是很简单。

关于checked的实现不能放在这里,因为当item被选中的时候,item的背景色不是取自Qt::BackgroundRole,同时前景色也不是取自Qt::ForegroundRole,因此这里处理不了。

如果非要让checked状态在这里实现也是有办法的,我们可以重写flags函数,让item不能被选中,这个办法博主是试过的,没有问题。 但是就存在一个隐,如果后期我们的item想被选中,就比较麻烦了。

基于以上设想,我们只需要这样重写flags函数,然后在data函数中返回checked行的背景色和前景色即可。

Qt::ItemFlags QRowModel::flags(const QModelIndex & index) const
{
return Qt::ItemIsEnabled;
}

2、flags函数

上一小节flags函数都已经展示出来了,item处于可用状态,这里还需要在添加上可选中状态,以免有其他坑

Qt::ItemFlags QRowModel::flags(const QModelIndex & index) const
{
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

以上就是model函数的重写了,比较简单,下面放出model的头文件

/**
* 简介: 主要提供接口 提供hover行
*/
class QRowModel : public QStandardItemModel
{
Q_OBJECT public:
explicit QRowModel(QObject * parent = 0);
~QRowModel(); private:
//hover时背景色 不建议外部直接调用
void SetHoverColor(const QColor & color);
QColor GetHoverColor() const { return m_HoverColor; } //设置当前hover行 不建议外部直接调用
void SetHoverRow(int row);
int GetHoverRow() const { return m_iHoverRow; } protected:
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; virtual Qt::ItemFlags flags(const QModelIndex & index) const override; private:
int m_iHoverRow = -1;//没有hover
QColor m_HoverColor = QColor(20, 22, 23); friend class QRowTable;
};

六、自定义视图

下面讲述今天的重头戏view。

首先需要搞清楚,重写视图需要完成哪些工作,才能更好的准备定位每个函数的意思。

1、目的

  1. hover时,把hover行通知到数据源
  2. 准确的hover和取消hover状态,这个问题确实搞了好久
  3. 点击item时,设置行选中色
  4. 指定列可排序

有了以上目标之后,我们逐个问题解决。

2、问题分析

针对以上4个目的,我们逐个分析解决办法

1、鼠标hover到这个比较简单,而且可以通过多种方式进行获取。

想要拿到这个状态,有一个很重要的属性需要开启:setMouseTracking(true);

a、如果我们重写的是QTableWidget这个类,那么可以去接收cellEntered这个信号

b、如果重写跟本篇文章一样,重写的QTableView这个类,那么我们需要重写mouseMoveEvent这个函数,然后通过indexAt函数获取当前行。

void QRowTable::mouseMoveEvent(QMouseEvent * event)
{
QTableView::mouseMoveEvent(event); const QModelIndex & index = indexAt(event->pos());
int row = -1;
if (index.isValid())
{
row = index.row();
} if (m_pModel->GetHoverRow() != row)
{
m_pModel->SetHoverRow(index.row());
viewport()->update();
}
}

2、取消hover装态

这个问题处理确实化了好长时间,主要还是想处理的办法更优雅,效率高一些。

这里为了实现不在item上时立刻取消hover状态,主要做了2件事。

第一件事

重写leaveEvent函数,鼠标离开时,恢复hover行为-1

void QRowTable::leaveEvent(QEvent * e)
{
if (m_pModel->GetHoverRow() != -1)
{
m_pModel->SetHoverRow(-1);
viewport()->update();
}
QTableView::leaveEvent(e);
}

第二件事

重写了QHeaderView,当鼠标在表头移动时,发送MouseMove信号,重置当前hover行为-1

void QRowHeader::mouseMoveEvent(QMouseEvent * event)
{
emit MouseMove(); QHeaderView::mouseMoveEvent(event);
}
auto callback = [this]{
if (m_pModel->GetHoverRow() != -1)
{
m_pModel->SetHoverRow(-1);
viewport()->update();
}
};
connect(vHeader, &QRowHeader::MouseMove, this, callback);
connect(hHeader, &QRowHeader::MouseMove, this, callback);

以上这个办法也是不得已为之,如果大家有更好的办法,欢迎评论区留言

3、点击item时设置当前行高亮背景色

第一小节的最后,我们也提到了,checked正行可以放到data函数中完成,但是由于我们的item有了可选择属性后,当前选中的item,或者选中行的背景色和前景色都是取自以下两个属性,因此这里我们只需要把这两个属性颜色值进行设置即可。

QPalette::Highlight
QPalette::HighlightedText

设置checked行颜色实现方式如下。

void QRowTable::SetCheckedColor(const QColor & color)
{
m_CheckedColor = color; QPalette palette = this->palette();
palette.setBrush(QPalette::Inactive, QPalette::Highlight, m_CheckedColor);
palette.setBrush(QPalette::Inactive, QPalette::HighlightedText, m_CheckedColor.lighter(255));
setPalette(palette);
}

如果仔细想一想,可能就会觉得有些问题,这里我们怎么去控制是一个单元格背景色还是整行背景色呢?

莫慌,加上以下两个属性即可,接口真的很简单,啥意思我就不说了。如果实现不知道的同学,欢迎评论区留言

setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QTableView::SingleSelection);//不能多选

4、 指定列排序

首先需要搞清楚Qt自带的排序处理逻辑,然后才可以对症下药,这里我也是跟了Qt自己代码,然后各种分析后,得出的处理方式。

Qt的代码分析这里不做讨论,有需要的同学私信吧。

各种代码跟踪后发现,当我们设置了setSortingEnabled为true时,Qt就支持排序了,并且在排序完成后会发给我们一个sortIndicatorChanged信号,这个信号主要是用来显示排序三角形的。

如果我们想不显示排序三角形,但是只是排序也是可以的,可以在接收这个信号后,调用setSortIndicatorShown接口隐藏三角形

为什么会这样麻烦呢?因为楼主跟踪Qt的代码了,发现如果排序了,Qt的三角形就是必须画出来的

void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
...
if (isSortIndicatorShown() && sortIndicatorSection() == logicalIndex)
opt.sortIndicator = (sortIndicatorOrder() == Qt::AscendingOrder)
? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp; ...
}

是不是很刺激,Qt太强大了,啥事情都给我们搞好了。

本篇文章我们主要是实现指定列不能进行排序,因此处理函数是这么干的,当接收到非排序列排序信号时,调用setSortingEnabled接口设置禁止排序。

void QRowTable::SortColumnChanged(int logicalIndex, Qt::SortOrder order)
{
if (m_Indicator.contains(logicalIndex) && m_Indicator[logicalIndex] == false)
{
if (isSortingEnabled())
{
setSortingEnabled(false);
}
}
else
{
if (isSortingEnabled() == false)
{
setSortingEnabled(true);
}
}
}

七、测试

1、view配置

QRowTable w;

//前两列不可排序
w.SetIndicatorVisible(0, false);
w.SetIndicatorVisible(1, false); //设置列最大宽度
w.SetColumnMinWidth(50); //设置列最小宽度
w.SetColumnMaxWidth(150); w.SetHoverColor(Qt::red);

2、model配置

QRowModel * model = w.GetModel();

QStringList headlist;
headlist << QStringLiteral("代码") << QStringLiteral("名称") << QStringLiteral("行业") << QStringLiteral("价格") << QStringLiteral("涨跌幅") << QStringLiteral("换手率");
model->setHorizontalHeaderLabels(headlist);

数据添加就跟我们平时往QStandardItemModel中放数据类似,代码太长就不放出来了。

八、相关文章

  1. Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等

  2. Qt高仿Excel表格组件-支持冻结列、冻结行、内容自适应和合并单元格

  3. 属性浏览器控件QtTreePropertyBrowser编译成动态库(设计师插件)

  4. 超级实用的属性浏览器控件--QtTreePropertyBrowser

  5. Qt之表格控件蚂蚁线

以上就是本篇文章的所有内容了,一个简易的整行hover、整行checked的表格

如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!!

很重要--转载声明

  1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords

  2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。


QRowTable表格控件-支持hover整行、checked整行、指定列排序等的更多相关文章

  1. Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等

    目录 一.概述 二.效果展示 三.定制表头 1.重写数据源 2.重写QHeaderView 四.设置属性 五.相关文章 原文链接:Qt实现表格控件-支持多级列表头.多级行表头.单元格合并.字体设置等 ...

  2. QRowTable表格控件(五)-重写表头排序、支持第三次单击恢复默认排序

    目录 一.原生表格 二.效果展示 三.实现方式 1.排序列定制 2.排序交互修改 四.相关文章 原文链接:QRowTable表格控件(五)-重写表头排序.支持第三次单击恢复默认排序 一.原生表格 开发 ...

  3. QRowTable表格控件(二)-红涨绿跌

    目录 一.开心一刻 二.概述 三.效果展示 四.任务需求 五.指定列排序 六.排序 七.列对其方式 八.相关文章 原文链接:QRowTable表格控件(二)-红涨绿跌 一.开心一刻 一天,五娃和六娃去 ...

  4. QRowTable表格控件(三)-效率优化之-合理使用QStandardItem

    目录 一.开心一刻 二.概述 三.效果展示 四.QStandardItem 1.QStandardItem是什么鬼 2.性能分析 3.QStandardItem使用上的坑 五.相关文章 原文链接:QR ...

  5. QRowTable表格控件(四)-效率优化之-优化数据源

    目录 一.开心一刻 二.问题分析 三.重写数据源 1.自己存储数据 2.重写data接口 四.比较 五.相关文章 原文链接:QRowTable表格控件(四)-效率优化之-优化数据源 一.开心一刻 一程 ...

  6. javascript - 可编辑表格控件 支持全键盘操作(无JS框架)

    项目中经常会用到表格编辑控件,网上也有不少,但是确实没有完全符合我要求的, 自己写一个吧! 1.该控件支持 数据显示列,文本编辑列,选择列,下拉列,索引列,删除列 六种列类型 2.支持全键盘操作,自定 ...

  7. devexpress表格控件gridcontrol设置隔行变色、焦点行颜色、设置(改变)显示值、固定列不移动(附源码)

    介绍一些常用的gridcontrol设置. 1.设置隔行变色.首先设置显示隔行变色,步骤:OptionsView-->EnableAppearanceEvenRow-->true和Opti ...

  8. Qt实现表格树控件-支持多级表头

    目录 一.概述 二.效果展示 三.实现方式 四.多级表头 1.数据源 2.表格 3.QStyledItemDelegate绘制代理 五.测试代码 六.相关文章 原文链接:Qt实现表格树控件-支持多级表 ...

  9. QTableView表格控件区域选择-自绘选择区域

    目录 一.开心一刻 二.概述 三.效果展示 四.实现思路 1.绘制区域 2.绘制边框 3.绘制 五.相关文章 原文链接:QTableView表格控件区域选择-自绘选择区域 一.开心一刻 陪完客户回到家 ...

随机推荐

  1. 数据绑定(二)把控件作为Binding源

    原文:数据绑定(二)把控件作为Binding源 下面的代码把一个TextBox的Text属性关联在了Slider的Value属性上 <Window x:Class="WpfApplic ...

  2. wpf中防止界面卡死的写法

    原文:wpf中防止界面卡死的写法 ); this.Dispatcher.BeginInvoke(new Action(() => { this.button1.Content = "计 ...

  3. QLocalServer与QLocalSocket进程通讯

    在Qt中,提供了多种IPC方法,作者所用的是QLocalServer和QLocalSocket.看起来好像和Socket搭上点边,实则底层是windows的name pipe.这应该是支持双工通信的. ...

  4. LOCK_TIMEOUT

    SET LOCK_TIMEOUT 1000 begin tran TranNameA select * from tablenameA WITH (updlock) where... waitfor  ...

  5. SQLServer 以备份初始化订阅

    原文:SQLServer 以备份初始化订阅 在创建事务复制时,如果发布数据库很大,使用快照初始化时,将等待很久,如果出现问题可能又得重新初始化.使用备份初始化会省很多时间,但是数据库在创建发布订阅期间 ...

  6. 零元学Expression Blend 4 - Chapter 18 用实例了解互动控制项「CheckBox」II

    原文:零元学Expression Blend 4 - Chapter 18 用实例了解互动控制项「CheckBox」II 延续上一章的CheckBox教学,本章将以实作继续延伸更灵活的运用CheckB ...

  7. 什么是DirectShow?

    DirectShow是微软出的用于流媒体开发的开发包.开发语言是C++,没提供C#接口的调用方式.

  8. create table as 复制not null

    创建一张表包含非空约束,唯一约束和check约束 SQL> create table dept( 2 ename varchar2(20) constraint mep_ename_nn not ...

  9. IdHTTP设置SSL证书,乱码问题也解决了

    要跟银行做接口,需要使用delphi来post数据,但对方提供的是https开头的网址,需要使用证书,对方已提供证书了,但是还是调用不成功,使用的是idhttp和TIdSSLIOHandlerSock ...

  10. 获取其他进程中StatusBar的文本

    (*// 标题:获取其他进程中StatusBar的文本 说明:Window2000+Delphi6调试通过 设计:Zswang 支持:wjhu111@21cn.com 日期:2005-02-22 // ...