鼠标在QTreeView、QTableView、QTableWidget项上移动,背景色改变

目录

1. 前言

2. 需求

3. 功能实现   

3.1. 代码实现

3.2. 功能讲解

4. 附录


1. 前言

       本博文用到了Qt的model/view framework框架,如果对Qt的“模型/视图/委托”框架不懂,本博文很难读懂。如果不懂这方面的知识,请在Qt Assistant 中输入Model/View Programming 学习了解。读者本机Qt安装目录下的Examples\Qt-XX.XX.XX\widgets\itemviews目录下有很多model/view framework的例子,可以进行自学了解,其中XX.XX.XX为Qt的版本号,如:5.14.1。
       因为QColumnView、QHeaderView、QListView、QTableView、QTreeView、QListWidget 、QUndoView、QTableWidget、QTreeWidget都是从QAbstractItemView继承,故本博文所说的技术点也适用于这些类,本博文以QTableView类来讲解。

2. 需求

      业务需求是:鼠标在QTableView的项上方移动(不是按下)时,项背景色改变。即像下面那样的效果:

3. 功能实现   

3.1. 代码实现

logTableView.h:

#ifndef LOG_TABLE_VIEW_H
#define LOG_TABLE_VIEW_H

#include <QTableView>


class CLogTableView : public QTableView
{
    Q_OBJECT

public:
    explicit CLogTableView(QWidget *parent = nullptr);

signals:

   // void mouseEnterItemSigal(const QModelIndex &);
private:

    /* 注意:不能重载mouseMoveEvent函数,否则QAbstractItemView::entered信号不会触发,
            如果非要重载mouseMoveEvent函数,则在该函数中发送自定义鼠标进入视图项的信号,如本 
            类中的mouseEnterItemSigal信号
    */
    //virtual void mouseMoveEvent(QMouseEvent *event) override;
};

#endif // LOG_TABLE_VIEW_H

logTableView.cpp:

#include "logTableView.h"
#include<QMouseEvent>
CLogTableView::CLogTableView(QWidget *parent)
    : QTableView(parent)
{
    setMouseTracking(true);
}

/* 注意:不能重载mouseMoveEvent函数,否则QAbstractItemView::entered信号不会触发,
        如果非要重载mouseMoveEvent函数,则在该函数中发送自定义鼠标进入视图项的信号,如本类
        中的mouseEnterItemSigal信号
*/
//void CLogTableView::mouseMoveEvent(QMouseEvent *event)
//{
//   auto pos = event->pos();
//   auto modelIndex = this->indexAt(pos);
//  // emit mouseEnterItemSigal(modelIndex);
//   //update();
//}
logTableModel.h:
#ifndef LOGTABLEMODEL_H
#define LOGTABLEMODEL_H

#include <QAbstractTableModel>

class CLogTableModel : public QAbstractTableModel
{
    Q_OBJECT

public:
    explicit CLogTableModel(QObject *parent = nullptr);

public:

    /*功能:向外层发送日志信息
     *参数1:日志具体内容
     *参数2:日志来源的模块,如:设备管理模块
     *参数3:日志级别
    */
    void addLog(const QString&qsLog, const QString&qsLogSrcModule, int nLogEvel);

private:
    // Basic functionality:
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;

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

    virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
private:
    QVariant doDecorationRole(int nLogEvel) const;

    QVariant doForegroundRole(int nLogEvel) const;


private:

    QStringList m_lstLogInfo;

};

#endif // LOGTABLEMODEL_H
logTableModel.cpp:
#include "logTableModel.h"
#include<QIcon>
#include<QBrush>

CLogTableModel::CLogTableModel(QObject *parent)
    : QAbstractTableModel(parent)
{
    
}

int CLogTableModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return static_cast<int>(m_lstLogInfo.size() / 3);
}

int CLogTableModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return 1;
}

QVariant CLogTableModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    auto rowIndex = index.row();
    auto rowCount = m_lstLogInfo.size() / 3;
    if((rowIndex < 0) || ( rowCount <= rowIndex))
    {
        Q_ASSERT(0);
        return QVariant();
    }

    // 以下这么做的目的是为了让最近产生的日志排在最顶部,最久产生的日志排在最底部
    auto logIndex = 3 * rowIndex;
    auto qsLog = m_lstLogInfo[logIndex];
    auto qsLogSrcModule = m_lstLogInfo[logIndex + 1];
    auto nLogEvel = m_lstLogInfo[logIndex + 2].toInt();

    auto columnIndex = index.column();

    switch (role)
    {
        case Qt::DisplayRole:
        {
            switch (columnIndex)
            {
                case 0:
                {
                   return qsLog;
                }
            }
        }
        break;
        case Qt::DecorationRole:
        {
            return doDecorationRole(nLogEvel);
        }
        break;
        case Qt::ForegroundRole:
        {
           return doForegroundRole(nLogEvel);
        }
        break;

    } // end switch role

    return QVariant();
}

Qt::ItemFlags CLogTableModel::flags(const QModelIndex &index) const
{
    Q_UNUSED(index);

    return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}

QVariant CLogTableModel::doForegroundRole(int nLogEvel) const
{
    switch (nLogEvel)
    {
        case 1:
        {
            return QBrush(Qt::yellow);
        }
        break;
        case 2
        case 3:
        {
            return QBrush(Qt::red);
        }
        break;
        default:
        {

        }
        break;
    }

    return QVariant();
}

QVariant CLogTableModel::doDecorationRole(int nLogEvel) const
{
    QIcon icon;
    switch (nLogEvel)
    {
        case 0:
        {
            icon.addFile(QLatin1String(":/logWnd/image/log/normal.png"));
            return icon;
        }
        break;
        case 1:
        {
            icon.addFile(QLatin1String(":/logWnd/image/log/warn.png"));
            return icon;
        }
        break;
        case 2:
        case 3:
        {
            icon.addFile(QLatin1String(":/logWnd/image/log/error.png"));
            return icon;
        }
        break;
        default:
        {
            return icon;
        }
       break;
    }

    return QVariant();
}


void CLogTableModel::addLog(const QString&qsLog, const QString&qsLogSrcModule, int nLogEvel)
{
    beginResetModel();

    if(m_lstLogInfo.size() >= 50)
    {
        m_lstLogInfo.clear();
    }

    auto qsLogEvel = QString::number(nLogEvel);
    m_lstLogInfo.insert(0, qsLog);
    m_lstLogInfo.insert(1, qsLogSrcModule);
    m_lstLogInfo.insert(2, qsLogEvel);

    endResetModel();
}

logItemDelegate.h:
#ifndef CLOGITEMDELEGATE_H
#define CLOGITEMDELEGATE_H

#include <QStyledItemDelegate>

class CLogItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    explicit CLogItemDelegate(QObject *parent = nullptr);

public:
     void enterItem(const QModelIndex &index);
private:
    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const override;

private:

     QModelIndex m_curIndex;
};

#endif // CLOGITEMDELEGATE_H

logItemDelegate.cpp:

#include "logItemDelegate.h"
#include<QPainter>

CLogItemDelegate::CLogItemDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
{
}

void CLogItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (m_curIndex.row() == index.row())
     {
        // 可以把第2个参数换成你想要的任何颜色
        painter->fillRect(option.rect, option.palette.highlight());
    }

    QStyledItemDelegate::paint(painter, option, index);
}


void CLogItemDelegate::enterItem(const QModelIndex &index)
{
    if(!index.isValid())
    {
        return;
    }

    m_curIndex = index;
}

调用方代码如下:

#include "logWnd.h"
#include "ui_logWnd.h"
#include<QPainter>
#include "logTableModel.h"
#include"logItemDelegate.h"

CLogWnd::CLogWnd(QWidget *parent) : QWidget(parent),
    ui(new Ui::CLogWnd)
{   
    ui->setupUi(this);
    this->resize(650, 1200);
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::Window);

    // 创建模型类
    m_pLogTableModel = new CLogTableModel(this);
    ui->logTv->setModel(m_pLogTableModel);

    // 创建委托类
    auto pLogItemDelegate = new CLogItemDelegate(this);
    ui->logTv->setItemDelegate(pLogItemDelegate);

    ui->logTv->horizontalHeader()->hide();
    ui->logTv->verticalHeader()->hide();
    ui->logTv->setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectRows);

    // 连接entered信号
    connect(ui->logTv, &CLogTableView::entered, pLogItemDelegate, &CLogItemDelegate::enterItem);

    // connect(ui->logTv, &QAbstractItemView::mouseEnterItemSigal, pLogItemDelegate, &CLogItemDelegate::enterItem);

}

3.2. 功能讲解

        功能实现说明如下:

  • CLogTableView类中将鼠标跟踪属性设置为true,否则不会捕捉QAbstractItemView类的entered信号。
  • 在槽函数CLogItemDelegate类的enterItem记录鼠标光标所在项目的模型索引。
  • 在委托类CLogItemDelegate中的paint函数中检测发现如果是鼠标光标所在项目的模型索引,则改变该项的背景色,否则就采用默认背景色。
  • 不能重载mouseMoveEvent函数,否则QAbstractItemView::entered信号不会触发,如果非要重载mouseMoveEvent函数,则在该函数中发送自定义鼠标进入视图项的信号,如本类中的mouseEnterItemSigal信号。

4. 附录

      现实中,经常发现QAbstractItemView类的entered信号不会激发,解决方法,参见:

QAbstractItemView类如:QTreeView、QTableView、QTableWidget不发送entered信号的问题解决

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一款适合程序员开发复杂系统的通用平台——JNPF 开发平台

在过去&#xff0c;很多开发工具更侧重代码编辑&#xff0c;针对数据库增删改查&#xff08;CRUD&#xff09;类的 Web 系统开发&#xff0c;在界面设计、前后端数据交互等环节主要还是靠写代码&#xff0c;效率比较低。目前很多所谓的低代码开发平台&#xff0c;大多数也都是基…

SQLServer数据库系列之:查询SQLServer数据库上面的连接信息、session信息、sql语句

SQLServer数据库系列之:查询SQLServer数据库上面的连接信息、session信息、sql语句 一、查询数据库上的连接信息二、查询SQLServer数据库的session信息SQLServer数据库从入门到精通系列文章之:SQLServer数据库百篇技术文章汇总 数据库专栏系列文章阅读传送门:详细整理汇总M…

超越 Siri 和 Alexa:探索LLM(大型语言模型)的世界

揭秘LLM&#xff1a;语言模型新革命&#xff0c;智能交互的未来趋势 近年来&#xff0c;虚拟助手的世界发生了重大转变。 虽然 Siri 和 Alexa 本身就是革命性的&#xff0c;但一种称为大型语言模型 (LLM) 的新型人工智能正在将虚拟助手的概念提升到一个全新的水平。 在这篇博文…

农业四情监测系统---气象科普

农业四情监测系统是一个集环境数据采集、分析与决策支持于一体的智能化系统。它主要通过对农田的土壤、气候、作物生长及病虫害等四个关键要素的实时监测&#xff0c;为农业生产提供精准的数据支持和科学的决策依据。 在土壤方面&#xff0c;系统能够检测土壤温度、湿度、pH值及…

我终于解决MathPage.wll文件找不到问题|(最新版Word上亲测)运行时错误,53’: 文件未找到:athPage.WLL

1、问题症状&#xff1a; 运行时错误&#xff0c;53’: 文件未找到:athPage.WLL 2、 解决方案 第一步 首先我们要先找到MathType安装目录下MathPage.wll文件&#xff0c;直接在此电脑中搜索MathPage.wll&#xff0c;找到文件所在位置。 第二步 打开Word文件&#xff0c…

App拉起微信小程序参考文章

App拉起微信小程序参考文章h5页面跳转小程序-----明文URL Scheme_weixin://dl/business/?appid*appid*&path*path*&qu-CSDN博客文章浏览阅读561次&#xff0c;点赞16次&#xff0c;收藏5次。仅需两步&#xff0c;就能实现h5跳转小程序&#xff0c;明文 URL Scheme&…

Linux---多线程(上)

一、线程概念 线程是比进程更加轻量化的一种执行流 / 线程是在进程内部执行的一种执行流线程是CPU调度的基本单位&#xff0c;进程是承担系统资源的基本实体 在说线程之前我们来回顾一下进程的创建过程&#xff0c;如下图 那么以进程为参考&#xff0c;我们该如何去设计创建一个…

闭包表(Closure Table)存储和查询树形数据结构

闭包表通过在关系表中记录树节点之间的直接和间接关系来表示节点之间的层次结构&#xff0c;目的是支持高效的树遍历和查询操作。 一、创建闭包表 CREATE TABLE departments (id int NOT NULL COMMENT ID,name varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_…

Redis冲冲冲——Redis持久化方式及其区别

目录 引出Redis持久化方式Redis入门1.Redis是什么&#xff1f;2.Redis里面存Java对象 Redis进阶1.雪崩/ 击穿 / 穿透2.Redis高可用-主从哨兵3.持久化RDB和AOF4.Redis未授权访问漏洞5.Redis里面安装BloomFilte Redis的应用1.验证码2.Redis高并发抢购3.缓存预热用户注册验证码4.R…

掌握React中的useCallback:优化性能的秘诀

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

XWPFDocument中XmlCursor的使用

类名&#xff1a; org.apache.xmlbeans Interface XmlCursor版本&#xff1a; 原xml代码&#xff1a; <w:p w14:paraId"143E3662" w14:textId"4167FBA7" w:rsidR"001506F2" w:rsidRPr"003F3D89" w:rsidRDefault"001506F2&qu…

OpenStack安装步骤

一、准备OpenStack安装环境 1、创建实验用的虚拟机实例。 内存建议16GB&#xff08;8GB也能运行&#xff09;CPU&#xff08;处理器&#xff09;双核且支持虚拟化硬盘容量不低于200GB&#xff08;&#xff01;&#xff09;网络用net桥接模式 运行虚拟机 2、禁用防火墙与SELin…

2024会声会影永久免费版新功能软件特色及新功能

会声会影2024永久免费版是一款收到很多用户公认的极佳视频编辑软件&#xff0c;里面的每一个功能都特别的强悍你能够一键给图片视频添加特效非常的过瘾&#xff0c;赶快来一起下载试试吧。 会声会影2023-安装包&#xff1a; https://souurl.cn/gtyDFc 会声会影2023-安装包&…

Golang 开发实战day03 - Arrays Slices

Golang 教程03 - Arrays&#xff0c;Slices Go语言中的数组和切片都是用于存储数据的类型&#xff0c;但它们之间存在一些重要的区别。了解这些区别对于有效地使用它们至关重要。 1. Arrays 数组 1.1 定义 数组是一种固定大小的数据结构&#xff0c;用于存储相同类型的值。…

web基础05-jQuery

目录 一、jQuery 1.概述 2.原生js与jQuery对比 3.特点 4.使用 &#xff08;1&#xff09;入口函数 &#xff08;2&#xff09;语法 &#xff08;3&#xff09;jQuery选择器 5.方法 &#xff08;1&#xff09;获取属性值&#xff1a; &#xff08;2&#xff09;删除属…

TCP三次握手,四次挥手状态转移过程

1.TCP状态转移过程 TCP连接的任意一端都是一个状态机,在TCP连接从建立到断开的整个过程中,连接两端的状态机将经历不同的状态变迁.理解TCP状态转移对于调试网络应用程序将有很大的帮助. 2.三次握手状态转换 3.四次挥手状态转换 4.TIME WAIT状态详解 为什么要有一个"TIME…

【网络安全】-数字证书

数字证书 数字证书是互联网通讯中用于标志通讯各方身份信息的一串数字或数据&#xff0c;它为网络应用提供了一种验证通信实体身份的方式。具体来说&#xff0c;数字证书是由权威的证书授权&#xff08;CA&#xff09;中心签发的&#xff0c;包含公开密钥拥有者信息以及公开密…

c# 调用ip2region组件 根据ip地址进行定位归属地运营商

需求描述&#xff1a;当项目中需要将IP转换成对应的归属地以及运营商&#xff0c;那么通过ip2region组件即可完美实现。 p2region本身支持net4.5以上&#xff0c;还有个ip2region.net组件&#xff0c;它要求net6及以上。所以&#xff0c;根据自己项目的需求即可选择其中一种方…

【SpringCloud微服务实战03】Nacos 注册中心

一、Nacos安装 官方文档安装Nacos教程:Nacos 快速开始 这里安装的是1.4.7版本,安装之后访问http://127.0.0.1:8848/nacos 管理界面如下:(用户名:nacos,密码:nacos) 二、Nacos服务注册和发现 1、在父工程中配置文件pom.xml 中添加spring-cloud-alilbaba的管理依赖:…

使用Docker实现Jenkins+Python + Pytest +Allure 接口自动化

一、Jenkins搭建 参考《Docker 安装 Jenkins》 进入 jenkins 容器 CLI 界面 docker exec -itu root jenkins /bin/bash二、准备条件 1、替换镜像内源 为了安装wget&#xff0c;默认用yum会安装不上wget命令&#xff0c;参考文章《docker容器内如何更换yum源【只想换成国内…