说在前面,本人也是近段时间刚开始学习Qt,实现上述功能的方法可能并不是最优,写此篇文章也是记录下学习的过程,也与大家分享一下。(在此先描述,后面会附上代码)(前面说的会比较基础)
首先,要使用QChartView类得现在.pro文件中加入:(得确保你的Qt中有QtCharts,可以在qt文件夹下include文件夹中查看)
QT += charts
同时需要在所创建的主窗口的.h文件下加入:
QT_BEGIN_NAMESPACE
class QChartView;
class QChart;
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
由于Qt6与Qt5中有些不太一样,NAMESPACE的使用方式也有所更改,所以不同的版本得按不同的规则来。(后面对坐标轴的建立及使用也有不一样的地方)
然后在ui设计界面拖入QGraphicsView并将其提升为QChartView,或是自建类。(本人所采用的是自建类的方式,所以本文主要按自建类的方式来说明。特别强调下,自建类更方便采用鼠标事件,建议使用自建类,自建类继承QChartView即可)
本文自建类的名称为chartview,如果没建立则基类选择QGraphics,提升的类名写自建类的名称即可。
最后在头文件中加入:(其实没啥先后顺序,都执行就行0.0)
#include <QtCharts>
就应该可以开始建立波形图了。建立方法如下:
首先先创建一个新的QChart指针、所需要画的线的指针(折线为QLineSeries,曲线为
QSplineSeries,散点为QScatterSeries)与坐标系指针。
QSplineSeries* line;
QChart* chart;
QValueAxis *axisX;
QValueAxis *axisY;
弄完这些就可以直接创建了图了:
QPen pen;
pen.setWidth(1);
pen.setColor(QColor(21, 100, 255));
m_Timer = new QTimer(this);
connect(m_Timer,SIGNAL(timeout()),this,SLOT(updata_plot()));
line = new QSplineSeries(this);
chart = new QChart();
chart->addSeries(line);
axisX = new QValueAxis(this);
axisY = new QValueAxis(this);
// line->setName("");//设置曲线名称
line->setPen(pen);//设置曲线颜色
line->setMarkerSize(2); //点大小
line->setUseOpenGL(true);//openGl 加速
// chart->setTitle("Pressure Data");//设置图标标题
chart->removeSeries(line);
chart->addSeries(line);
chart->addAxis(axisX,Qt::AlignBottom);
chart->addAxis(axisY,Qt::AlignLeft);
axisX->setRange(0,100);
axisY->setRange(0,10);
axisX->setLabelFormat("%.1f");
line->attachAxis(axisX);
line->attachAxis(axisY);
line->setPointsVisible(true);
ui->"这里是你创建的QChartView对象名"->setChart(chart);
大致创建就说到这里,主要还是说鼠标事件。
由于是自建类,不好调用ui(如果硬要调用也是可以的,但操作比较麻烦,不推荐)
简单做法就是直接信号与槽,即chartview下的鼠标事件发生后发送一个信号连接MainWindow下的槽函数,然后再槽函数中处理。(这里先附代码,再说方法)
chartview.h
#ifndef CHARTVIEW_H
#define CHARTVIEW_H
#include <QGraphicsView>
#include <QMouseEvent>
#include <QChartView>
#include <QWheelEvent>
class chartview : public QChartView
{
Q_OBJECT
public:
explicit chartview(QWidget *parent = nullptr);
signals:
void sendevent(QMouseEvent *ev);
void wheelevent(QWheelEvent *ev);
void relaeseevent(QMouseEvent *ev);
private slots:
void mouseMoveEvent(QMouseEvent *ev); //鼠标移动事件
void wheelEvent(QWheelEvent *ev); //鼠标滚动事件
void mouseReleaseEvent(QMouseEvent *ev);//鼠标释放事件
};
#endif // CHARTVIEW_H
chartview.c
#include "chartview.h"
#include <QDebug>
chartview::chartview(QWidget *parent)
: QChartView{parent}
{
}
void chartview::mouseMoveEvent(QMouseEvent *ev)
{
emit sendevent(ev);
}
void chartview::wheelEvent(QWheelEvent *ev)
{
emit wheelevent(ev);
}
void chartview::mouseReleaseEvent(QMouseEvent *ev)
{
emit relaeseevent(ev);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QtCharts>
#include <QTimer>
#include <QList>
#include <QWheelEvent>
#include <QMouseEvent>
QT_BEGIN_NAMESPACE
class QChartView;
class QChart;
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QTimer* m_Timer;
QLabel *label;
QSplineSeries* line;
QVector<QPointF> MV_reserve;
int max_reserve =1000;
//绘图变量与坐标
QChart* chart;
QValueAxis *axisX;
QValueAxis *axisY;
void creat_chartview(); //创建图表视图
public slots:
void updata_plot(); //更新图标视图
void chartmove(QMouseEvent *ev);
void wheelmove(QWheelEvent *ev);
void releasemove(QMouseEvent *ev);
private slots:
void on_pushButton_clicked();
};
#endif // MAINWINDOW_H
mainwindow.c
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "chartview.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_Timer = new QTimer(this);
m_Timer->start(10);
m_Timer->stop();
label = new QLabel(this);
label->setStyleSheet(QString("QLabel{color:#1564FF; font-family:\"Microsoft Yahei\"; font-size:10px; font-weight:bold;"
" background-color:rgba(21, 100, 255, 51); border-radius:4px; text-align:center;}"));
label->setFixedSize(58, 24);
label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
label->hide();
creat_chartview();
connect(ui->ShowChart0,&chartview::sendevent,this,&MainWindow::chartmove); //左键拖动右键拖动与悬浮
connect(ui->ShowChart0,&chartview::wheelevent,this,&MainWindow::wheelmove); //滚动
connect(ui->ShowChart0,&chartview::relaeseevent,this,&MainWindow::releasemove);//中键按下
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::creat_chartview()
{
QPen pen;
pen.setWidth(1);
pen.setColor(QColor(21, 100, 255));
connect(m_Timer,SIGNAL(timeout()),this,SLOT(updata_plot()));
line = new QSplineSeries(this);
chart = new QChart();
chart->addSeries(line);
axisX = new QValueAxis(this);
axisY = new QValueAxis(this);
// line->setName("");//设置曲线名称
line->setPen(pen);//设置曲线颜色
line->setMarkerSize(2);//点大小
line->setUseOpenGL(true);//openGl 加速
chart->removeSeries(line);
chart->addSeries(line);
chart->addAxis(axisX,Qt::AlignBottom);
chart->addAxis(axisY,Qt::AlignLeft);
axisX->setRange(0,100);
axisY->setRange(0,10);
axisX->setLabelFormat("%.1f");
line->attachAxis(axisX);
line->attachAxis(axisY);
line->setPointsVisible(true);
ui->ShowChart0->setChart(chart);
}
void MainWindow::updata_plot()
{
double left,right,err;
QVector<QPointF> newlist;
left = axisX->min();
right= axisX->max();
err=right-left;
MV_reserve = line->points();
// qDebug()<<MV_reserve.size();
if(MV_reserve.size() == max_reserve)
{
for(int i =1 ; i<max_reserve ;i++)
{
newlist.append(QPointF(i-1,MV_reserve.at(i).y()));
}
}
else
{
newlist = MV_reserve;
if(MV_reserve.size()>=right)
{
axisX->setRange(MV_reserve.size()-err,MV_reserve.size());
}
}
newlist.append(QPointF(MV_reserve.size(),rand()%10));
line->replace(newlist);
}
void MainWindow::wheelmove(QWheelEvent *ev) //鼠标滚动放大缩小指向区域
{
QPoint sroll = ev->angleDelta();
if(ev->position().x()>=60&&ev->position().x()<=ui->ShowChart0->width()-40
&&ev->position().y()>=80&&ev->position().y()<=ui->ShowChart0->height()-50)
{
double left,right,err;
double Currentpoint,changer,changel;
left = axisX->min();
right= axisX->max();
err=right-left;
Currentpoint = ((ev->position().x()-60)/(ui->ShowChart0->width()-100))*err+left;
if(sroll.y() > 0)
{
if(err>=10)
{
changer = right-(right-Currentpoint)*0.1;
changel = left+(Currentpoint-left)*0.1;
axisX->setRange(changel,changer);
}
}
else
{
changer = right+(right-Currentpoint)*0.1;
changel = left-(Currentpoint-left)*0.1;
if(changer>=MV_reserve.size()) {changer=MV_reserve.size();}
if(changel<=0) {changel=0; }
axisX->setRange(changel,changer);
}
}
}
void MainWindow::chartmove(QMouseEvent *ev) //鼠标左键点击拖动图片右键拖动缩放相关坐标轴
{
static QPoint last_posl,last_posr;
QPoint changepos;
QPoint now_pos;
double err,erry,left,right,height,bottom;
left = axisX->min();
right = axisX->max();
height = axisY->max();
bottom = axisY->min();
err = right-left;
erry = height-bottom;
if(ev->position().x()>=60&&ev->position().x()<=ui->ShowChart0->width()-40
&&ev->position().y()>=80&&ev->position().y()<=ui->ShowChart0->height()-50)//鼠标悬停
{
double nearposx,posy,posx,poserrx;
int selectx;
nearposx = left + (ev->position().x()-60)/(ui->ShowChart0->width()-100)*err;
//判断当前距离最近的一个点
if(int(nearposx*10)%10<5)
{
selectx = int(nearposx);
}
else
{
selectx = int(nearposx+1);
}
//求出一个比较好的范围
poserrx = (ui->ShowChart0->width()-100)/err;
if(poserrx<20)
{
poserrx/=2;
}
else
{
poserrx=10;
}
//判断该点是否在图中
if(line->at(selectx).y()<height+err*0.01)
{
posx = 60+((line->at(selectx).x()-left)/err)*(ui->ShowChart0->width()-100);
posy = 80+((height - line->at(selectx).y())/erry)*(ui->ShowChart0->height()-130);
if(ev->position().y()<=(posy+10)&&ev->position().y()>=(posy-10)
&&ev->position().x()<=(posx+poserrx)&&ev->position().x()>=(posx-poserrx))
{
label->setText(QString::asprintf("(%.1f,%d)", line->at(selectx).y(),(int)line->at(selectx).x()));
label->move(ev->position().x() +133, ev->position().y() +43);
label->show();
//在这生成一个qlabel
}
else
{
label->hide();
//在这隐藏生成的qlabel
}
}
if(MV_reserve.size()>=100&&ev->buttons()==Qt::LeftButton) 左键拖动
{
now_pos = ev->pos();
changepos = now_pos-last_posl;
last_posl = now_pos;
if(axisX->min()<=0&&changepos.x()>0)
{
axisX->setRange(0,err);
return;
}
else if(axisX->max()>=MV_reserve.size()-1&&changepos.x()<0)
{
axisX->setRange(MV_reserve.size()-err,MV_reserve.size());
return;
}
else
{
chart->scroll(-changepos.x(),changepos.y());
}
}
else
{
last_posl = ev->pos();
}
if(ev->buttons()==Qt::RightButton) 右键拖动
{
double changel,changer,changeh,changeb;
now_pos = ev->pos();
changepos = now_pos-last_posr;
last_posr = now_pos;
if(changepos.x()>0)
{
changel = left+err*0.01*changepos.x();
changer = right-err*0.01*changepos.x();
if((changer-changel)>=5)
{
axisX->setRange(left+err*0.01*changepos.x(),right-err*0.01*changepos.x());
}
}
else if(changepos.x()<0)
{
changel = left+err*0.01*changepos.x();
changer = right-err*0.01*changepos.x();
if(changel>=0&&changer<=MV_reserve.size())
{
axisX->setRange(changel,changer);
}
else
{
if(changel<0&&changer<=MV_reserve.size())
{
axisX->setRange(0,changer);
}
else if(changel>=0&&changer>MV_reserve.size())
{
axisX->setRange(changel,MV_reserve.size());
}
else
{
axisX->setRange(0,MV_reserve.size());
}
}
}
if(changepos.y()>0)
{
changeh = height+erry*0.01*changepos.y();
changeb = bottom-erry*0.01*changepos.y();
axisY->setRange(changeb,changeh);
}
else if(changepos.y()<0)
{
changeh = height+erry*0.01*changepos.y();
changeb = bottom-erry*0.01*changepos.y();
axisY->setRange(changeb,changeh);
}
}
else
{
last_posr = ev->pos();
}
}
}
void MainWindow::releasemove(QMouseEvent *ev) 鼠标中键点击缩小
{
if(ev->button()==Qt::MiddleButton
&&ev->position().x()>=70&&ev->position().x()<=ui->ShowChart0->width()-50
&&ev->position().y()>=90&&ev->position().y()<=ui->ShowChart0->height()-60)
{
double errx,leftx,rightx;
double erry,lefty,righty;
leftx = axisX->min();
rightx = axisX->max();
errx = rightx-leftx;
lefty = axisY->min();
righty = axisY->max();
erry = righty-lefty;
leftx-=errx*0.4;
rightx+=errx*0.4;
lefty-=erry*0.4;
righty+=erry*0.4;
if(leftx>=0&&rightx<=MV_reserve.size())
{axisX->setRange(leftx,rightx);}
else
{
if(leftx<=0&&rightx>=MV_reserve.size())
{axisX->setRange(0,MV_reserve.size());}
else if(leftx<=0)
{axisX->setRange(0,rightx);}
else
{axisX->setRange(leftx,MV_reserve.size());}
}
axisY->setRange(lefty,righty);
}
}
void MainWindow::on_pushButton_clicked()
{
if(m_Timer->isActive())
{
m_Timer->stop();
}
else
{
m_Timer->start();
}
}
左右键与悬停显示都是基于mousemoveevent,左键平移好理解,右键缩放也应该没啥问题,里面主要是对悬停比较麻烦,按理说应该可以用点的hover信号,但不知道为啥,这个信号的好像没那么稳定,所以只能自己写,大致就是先判断距离最近的点,再在该点周围画个框,判断鼠标是否在这个框里面,如果在,就show创建的label,不在就hide创建的label。
附上网盘:文章来源:https://www.toymoban.com/news/detail-491188.html
链接:https://pan.baidu.com/s/1CFOA82rWkepk3-tFQ2u4Cg
提取码:g2uh文章来源地址https://www.toymoban.com/news/detail-491188.html
到了这里,关于Qt6使用QChartView类与鼠标事件实现波形的缩放、平移、坐标轴单轴缩放与鼠标悬停显示点的数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!