QT之自定义表格控件

继承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]);
            }

        }
    }

}

你可能感兴趣的:(QT,qt,开发语言)