QT之自定义表格控件

news2024/10/5 17:20:21

请添加图片描述

继承QWidget来绘制的一款自定义控件,设计原因是因为Qt自带的QTableWidget的大批量操作很卡,特别是在嵌入式设备上时。
该控件特色功能:
1、支持拖动自适应。
2、支持各种颜色,字体,行列数设置。
代码如下:
.h

#ifndef MTABLEWIDGET_H
#define MTABLEWIDGET_H

#include <QWidget>
#include <QPainter>
#include <QMouseEvent>

class MTableWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MTableWidget(QWidget *parent = nullptr);
    ~MTableWidget();

    void moveScrollbar();

protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    void paintEvent(QPaintEvent *event);
    void timerEvent(QTimerEvent *event);
private:
    int m_verticalIndex;
    int m_rowNum;
    int m_sMaxline;
    int m_columnNum;
    int m_selectRow = -1;
    QString m_fontfamily;
    QFont m_titleFont;
    QColor m_brushColor;
    QColor m_textColor;
    QColor m_titleTextColor;
    QColor m_titleBackgroundColor;
    QRectF m_gridRectF;
    QRectF m_normalRectF;
    QRectF m_titleRectF;
    QRectF m_sliderTopRectF;
    QRectF m_sliderLeftRectF;
    QRectF m_sliderRightRectF;
    QRectF m_sliderBottomRectF;
    QPointF hpt;
    QStringList m_alarmList;
    QStringList m_titles;
    QList<QRectF> m_rowTextRectFList;
    QList<QRectF> m_columnTextRectFList;
    QList<QRectF> m_dataRectFList;
    QStringList m_datalist;
};

#endif // MTABLEWIDGET_H

.cpp

#include "mtablewidget.h"
#include "thread"
#include <QThread>
#include <QDebug>
bool m_bRelease;

MTableWidget::MTableWidget(QWidget *parent) :
    QWidget(parent)
{
    m_verticalIndex = 0;
    m_sMaxline = 20;
    // 获取列数属性值
    m_columnNum = 5;
    // 获取行数属性值
    m_rowNum = 5;
    // 获取报警文本字体属性
    m_fontfamily = "宋体";
    m_titleFont.setPixelSize(20);
    m_titleFont.setFamily(m_fontfamily);
    // 获取报警文本颜色属性值
    m_textColor = QColor("#ffffffff");
    // 获取brushClolr属性值
    m_brushColor = QColor("#ff000000");
    // 获取标题属性值
    m_titleBackgroundColor = QColor("#ff000000");
    //标题文本颜色
    m_titleTextColor = QColor("#ffffffff");

    m_titles.append("编号");
    m_titles.append("name1");
    m_titles.append("name2");
    m_titles.append("name3");
    m_titles.append("name4");

    startTimer(1000);
}

MTableWidget::~MTableWidget()
{
}

void MTableWidget::timerEvent(QTimerEvent *event)
{
    static int index = 0;
    m_datalist.append(QString::number(index));
    m_datalist.append(QString::number(index));
    m_datalist.append(QString::number(index));
    m_datalist.append(QString::number(index));
    m_datalist.append(QString::number(index));
    index++;
    update();
}

void MTableWidget::moveScrollbar()
{
    if(m_sliderTopRectF.contains(hpt))
    {
        if(m_datalist.size()>m_rowNum*3)
        {
            if(m_verticalIndex > 0)
                m_verticalIndex=m_verticalIndex-m_rowNum;

            if(m_verticalIndex<0)
                m_verticalIndex = 0;
        }
        else
        {
            m_verticalIndex = 0;
        }
    }
    else if(m_sliderBottomRectF.contains(hpt))
    {
        int dec = m_sMaxline;
        if(dec<10)
        {
            dec = 100;
        }
        if(m_datalist.size()>m_rowNum*3)
        {
            int size = m_datalist.size()/3;
            if(size>dec)
            {
                size = dec;
            }
            if((m_verticalIndex+m_rowNum)<size)
                m_verticalIndex=m_verticalIndex+m_rowNum;
        }
    }
    else if(m_sliderRightRectF.contains(hpt))
    {
        int dec = m_sMaxline;
        if(dec<10)
        {
            dec = 100;
        }
        if(m_datalist.size()/3 >= dec)
        {
            m_verticalIndex = dec - m_rowNum;
        }
        else
        {
            m_verticalIndex = (m_datalist.size()/3-1)/m_rowNum*m_rowNum;
        }
        if(m_verticalIndex<0)
            m_verticalIndex=0;
    }
    else if(m_sliderLeftRectF.contains(hpt))
    {
        m_verticalIndex = 0;
    }
}

void MTableWidget::mousePressEvent(QMouseEvent* event)
{
    m_bRelease = false;
    hpt = event->pos();
    qDebug()<<hpt<<m_gridRectF.top()<<m_gridRectF.top()+m_gridRectF.height()/m_rowNum;
    if (hpt.y() > m_gridRectF.top() && hpt.y() < m_gridRectF.top()+m_gridRectF.height()/m_rowNum)
    {
        m_selectRow = 0;
    }
    else if (hpt.y() > m_gridRectF.top()+m_gridRectF.height()/m_rowNum && hpt.y() < m_gridRectF.top()+2*m_gridRectF.height()/m_rowNum)
    {
        m_selectRow = 1;
    }
    else if (hpt.y() > m_gridRectF.top()+2*m_gridRectF.height()/m_rowNum && hpt.y() < m_gridRectF.top()+3*m_gridRectF.height()/m_rowNum)
    {
        m_selectRow = 2;
    }
    else if (hpt.y() > m_gridRectF.top()+3*m_gridRectF.height()/m_rowNum && hpt.y() < m_gridRectF.top()+4*m_gridRectF.height()/m_rowNum)
    {
        m_selectRow = 3;
    }
    else if (hpt.y() > m_gridRectF.top()+4*m_gridRectF.height()/m_rowNum && hpt.y() < m_gridRectF.top()+5*m_gridRectF.height()/m_rowNum)
    {
        m_selectRow = 4;
    }
    else
        m_selectRow = -1;

    std::thread th([=](){
        while(1)
        {
            moveScrollbar();
            QThread::msleep(400);
            if(m_bRelease)
                break;
        }
        return 0;
    });
    th.detach();
    update();
}

void MTableWidget::mouseReleaseEvent(QMouseEvent* event)
{
    m_bRelease = true;
}

void MTableWidget::paintEvent(QPaintEvent *event)
{
    QPainter p(this);
    QRectF rectF = rect();

    QFontMetrics f1(m_titleFont);
    QFontMetrics f2(m_titleFont);
    int V_SLIDER_H = f1.height()*5;             //标题栏高度
    int H_SLIDER_W = 60;
    int H_SLIDER_H = 40;                        //垂直滑块的高度
    int NO_W = 0;                               //自带编号列宽度
    H_SLIDER_W = (H_SLIDER_W+10)*2;
    if(V_SLIDER_H<=25)
        V_SLIDER_H=25;
    if(H_SLIDER_W<=70)
        H_SLIDER_W=70;

    m_rowTextRectFList.clear();
    m_columnTextRectFList.clear();
    m_dataRectFList.clear();
    // 控件区域
    m_normalRectF = rectF.normalized();

    // 上边标题区域
    m_titleRectF = QRectF(m_normalRectF.x(),
                          m_normalRectF.top(),
                          m_normalRectF.width(),
                          V_SLIDER_H);
    // 单行高
    double singleHeight = (m_normalRectF.height()-H_SLIDER_H-V_SLIDER_H)/(m_rowNum);//原来是1
    // 单列宽
    double singleWidth = (m_normalRectF.width()-NO_W)/(m_columnNum);

    // 绘制背景矩形
    p.setPen(m_brushColor);
    p.setBrush(QBrush(m_brushColor));
    p.drawRect(m_normalRectF);

    // 绘制上边标题区域
    p.setBrush(QBrush(m_titleBackgroundColor));
    p.drawRect(m_titleRectF);
    p.setPen(QPen(m_brushColor));

    QRectF gridRectF;
    gridRectF.setX(m_normalRectF.x());
    gridRectF.setY(m_normalRectF.y() + V_SLIDER_H);
    gridRectF.setWidth(m_normalRectF.width());
    gridRectF.setHeight(m_normalRectF.height()- V_SLIDER_H - H_SLIDER_H);
    m_gridRectF = gridRectF;

    //绘制选中行矩形框
    if (m_selectRow >= 0)
    {
        p.setPen(QPen("#2e2729"));
        p.setBrush(QBrush("#2e2729"));
        p.drawRect(m_normalRectF.x(),gridRectF.top()+m_selectRow*gridRectF.height()/m_rowNum
                   ,m_normalRectF.width(),gridRectF.height()/m_rowNum);
    }

    // 绘制行线
    p.setPen(m_textColor);
    for (int i = 1; i <= m_rowNum; i++)
    {
        p.drawLine(m_normalRectF.x(),
                          gridRectF.top()+(i-1)*gridRectF.height()/(m_rowNum),
                          gridRectF.right(),
                          gridRectF.top()+(i-1)*gridRectF.height()/(m_rowNum));
    }
    p.drawLine(m_normalRectF.x(),           //第一行
                      m_normalRectF.y(),
                      gridRectF.right(),
                      m_normalRectF.y());
    p.drawLine(m_normalRectF.x(),           //最后一行
                      gridRectF.top()-1+gridRectF.height(),//移动1
                      gridRectF.right(),
                      gridRectF.top()-1+gridRectF.height());//移动1
#if 1
    // 绘制列线
    for (int i = 1; i <= m_columnNum; i++)
    {
        p.drawLine(gridRectF.left()+NO_W+i*(gridRectF.width()-NO_W)/m_columnNum,
                          m_normalRectF.top(),
                          gridRectF.left()+NO_W+i*(gridRectF.width()-NO_W)/m_columnNum,
                          gridRectF.bottom());

    }
    p.drawLine(gridRectF.left(),                   //第一列
                      m_normalRectF.top(),
                      gridRectF.left(),
                      gridRectF.bottom());
    p.drawLine(gridRectF.left()+NO_W,   //第二列
                      m_normalRectF.top(),
                      gridRectF.left()+NO_W,
                      gridRectF.bottom());
    p.drawLine(gridRectF.left()+gridRectF.width(),  //最后一列
                      m_normalRectF.top(),
                      gridRectF.left()+gridRectF.width(),
                      gridRectF.bottom());
#endif
    for (int i = 1; i < m_rowNum+1; i++)
    {
        // 数据区单元格矩形框列表
        for (int j = 0; j < m_columnNum; j++)
        {
            m_dataRectFList << QRectF(gridRectF.left()+NO_W+j*(gridRectF.width()-NO_W)/m_columnNum,
                                      gridRectF.top()+(i-1)*gridRectF.height()/(m_rowNum),
                                      (gridRectF.width()-NO_W)/m_columnNum,
                                      gridRectF.height()/(m_rowNum));
        }
#if 0
        // 编号文本矩形框列表
        for (int i = 1; i < m_rowNum+1; i++)
        {
            m_rowTextRectFList << QRectF(m_normalRectF.left(),
                                         m_normalRectF.top()+V_SLIDER_H+(i-1)*singleHeight,
                                         NO_W,
                                         singleHeight);
        }
#endif

        // 标题栏文本矩形框列表
        for (int i = 1; i < m_columnNum+1; i++)
        {
            m_columnTextRectFList << QRectF(m_normalRectF.left()+NO_W+(i-1)*singleWidth,
                                            m_normalRectF.top(),
                                            singleWidth,
                                            m_gridRectF.top()-m_normalRectF.top());
        }

        // 绘制标题文本
        p.setPen(m_titleTextColor);
        p.setFont(m_titleFont);

        for(int i = 0;i<m_columnNum;i++)
        {
            p.drawText(m_columnTextRectFList[i],
                              Qt::AlignCenter, m_titles[i]);
        }
    }

    // 水平滚动区域
    p.setPen(QPen("#2e2729"));
    p.setBrush(QBrush("#2e2729"));
    p.drawRect(m_normalRectF.left(), m_normalRectF.bottom()-H_SLIDER_H, m_normalRectF.width(), H_SLIDER_H+1);
    p.setBrush(QBrush("#9e2729"));
    m_sliderTopRectF =    QRectF(m_normalRectF.right()-H_SLIDER_W-H_SLIDER_W-10, m_normalRectF.bottom()-H_SLIDER_H, H_SLIDER_W, H_SLIDER_H);
    m_sliderBottomRectF = QRectF(m_normalRectF.right()-H_SLIDER_W, m_normalRectF.bottom()-H_SLIDER_H, H_SLIDER_W, H_SLIDER_H);
    p.drawRect(m_sliderTopRectF);
    p.drawRect(m_sliderBottomRectF);
    m_sliderLeftRectF =  QRectF(m_normalRectF.left()-1,                        m_normalRectF.bottom()-H_SLIDER_H, H_SLIDER_W, H_SLIDER_H);
    m_sliderRightRectF = QRectF(m_normalRectF.left()+H_SLIDER_W+10,                        m_normalRectF.bottom()-H_SLIDER_H, H_SLIDER_W, H_SLIDER_H);
    p.drawRect(m_sliderLeftRectF);
    p.drawRect(m_sliderRightRectF);
    p.setPen(Qt::white);
    p.drawText(m_sliderTopRectF,Qt::AlignCenter,QObject::tr("上一页"));
    p.drawText(m_sliderBottomRectF,Qt::AlignCenter,QObject::tr("下一页"));
    p.drawText(m_sliderLeftRectF,Qt::AlignCenter,QObject::tr("首页"));
    p.drawText(m_sliderRightRectF,Qt::AlignCenter,QObject::tr("尾页"));

    // 绘制信息
    p.setPen(Qt::black);
    QStringList strList;
    m_alarmList.clear();
    for (int i = 0;i < m_datalist.size();i++)
    {
        strList.append(m_datalist.at(i));
    }

    if(!m_alarmList.isEmpty())
    {
        p.setPen(m_brushColor);
    }

    QPen pen;
    pen.setColor(m_textColor);
    p.setPen(pen);
#if 0
    // 绘制编号
    p.setFont(m_titleFont);
    int ind = m_verticalIndex;
    for(int i = 0;i<m_rowNum;i++)
    {
        p.drawText(m_rowTextRectFList[i], Qt::AlignCenter,
                          QString::number(ind+1));

        ind++;
    }
#endif

    // 绘制表格数据
    int num = strList.count()/m_columnNum;
    for (int i = 0; i < m_rowNum; i++)
    {
        for (int j = 0; j < m_columnNum; j++)
        {
            if (strList.count() > ((m_verticalIndex+i)*m_columnNum+j))
            {
                int currentrow = (num-1-i-m_verticalIndex)*m_columnNum+j;

                if(currentrow<0)
                    currentrow = 0;

                p.drawText(m_dataRectFList[i*m_columnNum+j],
                        Qt::AlignCenter,
                        strList[currentrow]);
            }

        }
    }

}

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

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

相关文章

win10安装cuda11.4及cudnn

查看nvidia驱动版本 在windows终端键入nvidia-smi&#xff0c;查看nvidia显卡驱动。显卡驱动的版本决定了CUDA的版本下限。 如果出现上述的问题&#xff0c;则终端进入C:\Program Files\NVIDIA Corporation\NVSMI文件夹内&#xff0c;再键入nvidia-smi&#xff0c;可以看到我…

[MySQL]MySQL视图特性

[MySQL]MySQL视图特性 文章目录 [MySQL]MySQL视图特性1. 视图的概念2. 视图的基本操作创建视图删除视图 3. 视图规则和限制 1. 视图的概念 视图是一个虚拟表&#xff0c;其内容由查询定义&#xff0c;同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数据。基表是对…

Git标签管理(对版本打标签,起别名)

tag 理解标签创建标签git tag [name]git show [tagname] 操作标签删除标签git tag -d < tagname > 推送某个标签到远程git push origin < tagname > 理解标签 标签 tag &#xff0c;可以简单的理解为是对某次 commit 的⼀个标识&#xff0c;相当于起了⼀个别名。 …

数据库备份mysqldump、mydumper、xtrabackup

数据库备份&#xff0c;数据库为school&#xff0c;素材如下 1.创建student和score表 CREATE TABLE student ( id INT(10) NOT NULL UNIQUE PRIMARY KEY , name VARCHAR(20) NOT NULL , sex VARCHAR(4) , birth YEAR, department VARCHAR(20) , address VARCHAR(50) );创建sco…

《面试1v1》如何提高远程用户的吞吐量

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

FPGA配置文件从串并模式下载

FPGA配置文件的下载模式有5种&#xff1a; 主串模式&#xff08;master serial&#xff09;从串模式&#xff08;slave serial&#xff09;主并模式&#xff08;master selectMAP&#xff09;从并模式&#xff08;slave selectMAP&#xff09;JTAG模式 其中&#xff0c;JTAG模…

SQL 常见函数整理 _ SOUNDEX() 和 DIFFERENCE()

SOUNDEX() 1. 用法 是一种针对字符串进行音似匹配的函数。它将一个字符串作为输入&#xff0c;并返回一个代表该字符串音似编码的字符串。此编码可用于比较和匹配具有相似发音的字符串。 2. 基本语法 SOUNDEX(expression)其中&#xff0c;expression 是要进行音似编码的字符串…

后端排序优化——谁调用,谁排序

前言 为了使排序更加灵活&#xff0c;建议后端排序可以优化为“谁调用谁排序”。 代码实现 数据库设计 以学生表为例。 前端查询条件为姓名&#xff0c;住址。 Controller 简化后的controller层代码如下&#xff1a; /*** queryStudent[查询学生]* param name 姓名* param …

SQL优化——update优化

1.update优化 执行update语句的时候一定要根据索引字段进行更新&#xff0c;否则就会出现行锁升级为表锁的情况&#xff0c;锁住整张表&#xff0c;一旦锁表了并发性能就会受影响。 2.总结 sql优化事实上都是对索引进行优化

【Git】—— 解决分支合并冲突

在实际分⽀合并的时候&#xff0c;并不是想合并就能合并成功的&#xff0c;有时候可能会遇到代码冲突的问题。 为了演⽰这问题&#xff0c;创建⼀个新的分⽀ dev1 &#xff0c;并切换⾄⽬标分⽀&#xff0c;我们可以使⽤ git checkout - b dev1 ⼀步完成创建并切换的动作…

网卡收发包系统结构收发包流程,tcp/ip协议,socket套接字缓冲区,滑动窗口,mtu/mss

MTU和MSS的区别 MTU和MSS的区别 TCP 的 MTU & MSS MTU是在那一层&#xff1f;MSS在那一层&#xff1f; MTU是在数据链路层的载荷大小也就是传给网络层的大小&#xff0c;mss是在传输层的载荷大小也就是传给应用层的大小 mss是根据mtu得到的 1、MTU&#xff1a; Maximu…

矩阵置零(力扣)思维 JAVA

给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 输入&#xff1a;matrix [[0,1,2,0],[3,4,5,2],[…

Django项目之模型

Django项目之模型 创建环境配置连接MySQL数据库创建表单注册模型Django模型类查询模型类的条件查询聚合函数 创建环境 创建Django项目&#xff0c;创建usersapp&#xff0c;并在setting.py中注册 项目工作目录 配置连接MySQL数据库 修改/Djweb/Djweb/setting.py中DATABASE…

netty知识集锦2

粘包半包 粘包半包解决方案&#xff0c; 1短链接&#xff0c;它的消息边界是从链接建立到链接断开 2.定长解码器&#xff1a;服务器端选最大长度的消息作为定长&#xff0c;客户端不足补齐&#xff0c;缺点造成浪费 netty协议设计与解析 Message编码解码

[DASCTF 2023 0X401七月暑期挑战赛] REV1 controlflow复现

这东西没怎么研究过&#xff0c;不过很多人都完成了&#xff0c;不过这种比赛有很多应该是拿的别人的wp&#xff0c;所以减去些水份&#xff0c;赛后拿到一个wp是人c程序实现的。然后根据原代码还原一下加密流程。 首先是main 这里比较特殊&#xff0c;一开始的3个变量明显是加…

VS2010打开VC6工程进行调试时的问题解决方法

VS2010打开VC6工程进行调试时的问题解决方法 在工程属性页&#xff0c;“配置属性—链接器—输入—忽略特定默认库” 中添加编译时提示无法找到的几个lib库&#xff0c;如下图所示

【iOS】App仿写--管理系统

文章目录 前言一、账号界面二、功能界面三、添加功能四、删除功能五、更改功能六、查找功能七、排序功能八、退出功能总结 前言 在日常生活中&#xff0c;如果用文字来记述与管理我们数据会十分麻烦&#xff0c;并且人工成本较高&#xff0c;这里笔者给出一种管理系统的模版&a…

DSP开发软件css(10)使用基础(汉化、工程导入、设置目标配置文件、选择仿真器和芯片型号、添加文件|库路径、编译下载等操作)

DSP开发软件css(10)使用基础(汉化、工程导入、设置目标配置文件、选择仿真器和芯片型号、添加文件|库路径、编译下载等操作&#xff09; 文章目录 DSP开发软件css(10)使用基础(汉化、工程导入、设置目标配置文件、选择仿真器和芯片型号、添加文件|库路径、编译下载等操作&#…

中医-十二经-图

&#x1f33c;十二经-图 &#x1f354;十二经&#x1f36d;任脉、督脉&#x1f957;冲脉、带脉&#x1f96a;阴维、阳维&#x1f368;资源下载 &#x1f354;十二经 &#x1f36d;任脉、督脉 &#x1f957;冲脉、带脉 &#x1f96a;阴维、阳维 &#x1f368;资源下载 如果需要…

SESSION,TOKEN和Postman的使用

SESSION&#xff1a;它是存储在服务端的 1、客户端输入账户和密码&#xff0c;登录成功&#xff0c;在服务端生成一个SESSIONID同时存储在服务端&#xff08;DB or Redis&#xff09; 2、服务端把生成的SESSIONID通过响应头中的Set-Cookie返回给客户端 3、再系统下个请求中&…