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