公司需求需要绘制散点图。
在QT下实现散点图有几种方式,
1)采用Qt自带的QtCharts库,自行查看相应API即可实现散点图的绘制,需要注意坐标轴的问题,但是这个方式实现散点图在大数据量下机器会异常卡顿故pass.
2)采用Qt的Qt QPainter也就是网上说的画家来实现散点图,该方法实现起来比较麻烦但是性能优于QtCharts,每个地方都是需要自己去画。实现效果如下
具体实现采用QtPainter 和 QPixMap来实现。不重写paintEvent这个方法,也就是说在paintEvent外来实现画图。如果基于paintEvent来实现的画必须是基于QWidget,QtPainter传入当前窗口对象。每次进行update时会重新绘制窗口所有元素。
代码如下
//头文件
#ifndef SCATTER_H
#define SCATTER_H
#include <QWidget>
#include <QPainter>
#include <QLabel>
#include<QComboBox>
#include <QPaintEvent>
#include <QTimer>
#include <QTime>
const int ORIGIN_X=35; //定义原点X
const int ORIGIN_Y=220;//定义原点Y
const int WIDTH_X=320;//定义X轴宽度
const int HEIGTH_Y=200;//定义Y轴高度
const int MAX_X=65535;
const int MAX_Y=65535;
const int MIN_X=0;
const int MIN_Y=0;
class Scatter : public QWidget
{
Q_OBJECT
public:
explicit Scatter(QWidget *parent = nullptr);
QPixmap mPixMap;
QLabel *mLabel;
QTimer *one;
QComboBox *mXAisle;
QComboBox *mYAisle;
QComboBox *mXCondition;
QComboBox *mYCondition;
double XScale;
double YScale;
signals:
public slots:
void Paint();
};
#endif // SCATTER_H
//具体实现
#include "scatter.h"
#include<QDebug>
Scatter::Scatter(QWidget *parent) : QWidget(parent)
{
//该类需要指定一个父窗口
this->resize(480,300);
XScale=320.0/65535.0; //坐标系数,用宽/高来除以该坐标轴的最大值-最小值得到一个系数,然后用实际的数据X这个系数得到的就是实际坐标轴上的坐标了
YScale=200.0/65535.0;
mLabel=new QLabel(this); //该控件用来装图片,后面用于显示
mLabel->setGeometry(80,0,400,250);
//mXAisle=new QComboBox(this);
// mXAisle->setGeometry(20,250,50,20);
// mYAisle=new QComboBox(this);
// mYAisle->setGeometry(0,10,75,35);
// mXAisle->insertItem(0,"AAAAAAA");
mPixMap=QPixmap(400,250);//初始化图片
mPixMap.fill(Qt::white);
QPainter painter(&mPixMap);
painter.setRenderHint(QPainter::Antialiasing, true);//设置反锯齿模式
QPen pen;
pen.setColor(Qt::black);
pen.setWidth(2);
painter.setPen(pen);
painter.drawLine(ORIGIN_X,ORIGIN_Y,ORIGIN_X+WIDTH_X,ORIGIN_Y);//X轴 自己需要定义一个原点 但是此时的实际坐标还是左上角,后面进行数据处理时,需要进行坐标转换,画家画线,起点是自己定义的坐标,终点是自己定义的坐标加上自己定义X,Y轴的长度,这个时候得到X Y轴
painter.drawLine(ORIGIN_X,ORIGIN_Y-HEIGTH_Y,ORIGIN_X,ORIGIN_Y);//Y轴
//绘制原点 X 绘制原点的0
painter.drawLine(ORIGIN_X,ORIGIN_Y,ORIGIN_X,ORIGIN_Y+5);
painter.drawText(ORIGIN_X,ORIGIN_Y+15,QString::number(MIN_X));
//绘制原点 Y
painter.drawLine(ORIGIN_X-5,ORIGIN_Y,ORIGIN_X,ORIGIN_Y);
painter.drawText(ORIGIN_X-15,ORIGIN_Y,QString::number(MIN_Y));
//绘制X轴 绘制X轴的刻度线,分几个刻度就遍历几次,
for(int i=0;i<2;i++)
{
painter.drawLine(ORIGIN_X+(i+1)*(WIDTH_X/2),ORIGIN_Y,ORIGIN_X+(i+1)*(WIDTH_X/2),ORIGIN_Y+5);
painter.drawText(ORIGIN_X+(i+1)*(WIDTH_X/2)-20,ORIGIN_Y+20,QString::number((i+1)*(MAX_X/2)));
}
//绘制Y轴
for(int i=0;i<2;i++)
{
painter.drawLine(ORIGIN_X-5,ORIGIN_Y-(i+1)*(HEIGTH_Y/2),ORIGIN_X,ORIGIN_Y-(i+1)*(HEIGTH_Y/2));
painter.translate(ORIGIN_X-15,ORIGIN_Y-(i+1)*(HEIGTH_Y/2)+5);
painter.rotate(-90);
painter.drawText(-30,0,QString::number((i+1)*(MAX_Y/2)));
painter.resetTransform();
}
mLabel->setPixmap(mPixMap);//这是把图片设置到控件中去,从而达到显示的目的
mLabel->adjustSize();//自适应大小
one=new QTimer();
connect(one,SIGNAL(timeout()),this,SLOT(Paint()));
one->start(100);
}
void Scatter::Paint()
{
QPainter painter(&mPixMap);
QPen pen;
pen.setColor(Qt::red);
pen.setWidth(2);
painter.setPen(pen);
QTime time= QTime::currentTime();
qsrand(time.msec()+time.second()*1000);
double x=qrand()%65535;
double y=qrand()%65535;
qDebug()<<x<<y;
painter.drawPoint(ORIGIN_X+(x*XScale),ORIGIN_Y-(y*YScale));
mLabel->setPixmap(mPixMap);
mLabel->adjustSize();
}
如有错误,欢迎指正,希望共同进步。