前言
QtCharts是Qt提供的一个用于创建交互式图表的模块。Qt5.7之前,只有商业版本也搭载,在此之后,其community版本也搭载了Qtcharts模块。QtCharts支持绘制多种常见图表类型,常见的有:折线图、柱状图、饼图、散点图、区域图等。本文软件采用的是Qt Creator 4.3.1 Community,搭载Qt5.9版本,以根据主窗口数据数据弹出对话框动态绘制折线图为例。
参考链接:https://blog.csdn.net/qq153471503/article/details/122078179
QT多界面之间数据传输_qt主界面向子界面发送信息-CSDN博客
本文完整示例代码下载:https://download.csdn.net/download/cp_freshman/88593418?spm=1001.2014.3001.5501
1 利用QChart绘图的组成部分相关介绍
有关QChart、QChartView、QLineSeries、QValueAxis的介绍可参考链接1。
准备工作需要注意以下几个地方:
1、安装Qt时候要勾选QChart模块,本次实例是基于Qt5.9的,按照默认的安装流程走的,已经安装过QChart模块。
2、新建项目时,生成的.pro文件默认是QT += core gui,需要将其改为QT += core gui charts引入QChart模块。
2 设计自定义对话框类
自定义对话框类用于接收主窗口发送的数据,并利用数据画出二维图。主要步骤如下:
1)创建Qt设计师界面类
鼠标右击项目文件夹,选择添加新文件,选中Qt,选择QT设计师界面类
可以看到有如下几个模板:底部带有按钮的对话框类、右侧带有按钮对话框的类、不带按钮的对话框类、MainWindow类、Widget类等。本次实例自定义对话框仅为了显示二维图,故选择不带按钮的对话框类。
点击下一步,为自定义类命名为MyDialog,点击下一步直至出现完成按钮
在mydialog.ui中添加一个QGraphicsView,右击将其提升为QChartView:
2)代码
mydialog.h文件
注意: 在自定义界面类中使用QCharts,除了需要在光添加头文件QChartView还不够,还需要引入QChart的命名空间,使用宏QT_CHARTS_USE_NAMESPACE。主窗口和自定义对话框之间的信息传递是通过Qt中含参信号和槽函数实现的,同时该自定义槽函数不能写在私有private下,要写在public下,否则主窗口无法调用该槽函数。
#ifndef PLOTDIALOG_H
#define PLOTDIALOG_H
#include <QDialog>
#include <QChartView>
#include <QValueAxis>
#include <QLineSeries>
/* 光添加头文件QChartView还不够,还需引入Qchart的命名空间*/
QT_CHARTS_USE_NAMESPACE
namespace Ui {
class PlotDialog;
}
class PlotDialog : public QDialog
{
Q_OBJECT
public:
explicit PlotDialog(QWidget *parent = 0);
~PlotDialog();
void qDebug_recv(float &,float &);//主窗口含参信号对应的槽函数
private:
Ui::PlotDialog *ui;
private:
/* 图标对象 */
QChart * m_chart;
/* 横纵深坐标轴对象 */
QValueAxis *m_axisX, *m_axisY,*m_axisZ;
/* 曲线图对象 */
QLineSeries *m_lineSeries;
private slots:
};
#endif // PLOTDIALOG_H
mydialog.cpp文件
#include "plotdialog.h"
#include "ui_plotdialog.h"
#include <QDebug>
PlotDialog::PlotDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::PlotDialog)
{
ui->setupUi(this);
m_axisX = new QValueAxis();
m_axisY = new QValueAxis();
m_axisZ = new QValueAxis();
m_axisX->setTitleText("X");
m_axisY->setTitleText("Y");
m_axisZ->setTitleText("Z");
// m_axisX->setMin(0);
// m_axisY->setMin(0);
// m_axisZ->setMin(0);
// m_axisX->setMax(10);
// m_axisY->setMax(10);
// m_axisZ->setMax(10);
m_lineSeries = new QLineSeries(); //创建曲线绘制对象
m_lineSeries->setPointsVisible(false); //设置数据点可见
m_lineSeries->setName("AUV位置实时变化图像"); //图例名称
m_chart = new QChart(); //创建图表对象
m_chart->resize(800,400);
m_chart->addAxis(m_axisX,Qt::AlignBottom); //将X轴添加到图表上
m_chart->addAxis(m_axisY,Qt::AlignLeft); //将Y轴添加到图表上
m_chart->addSeries(m_lineSeries); //将曲线对象添加到图表上
m_chart->setAnimationOptions(QChart::SeriesAnimations);// 动画:能使曲线绘制显示的更平滑,过渡效果更好看
m_lineSeries->attachAxis(m_axisX); //曲线对象关联上x轴,此步骤必须在m_chart->addSeries之后
m_lineSeries->attachAxis(m_axisY); //曲线对象关联上y轴,此步骤必须在m_chart->addSeries之后
ui->graphicsView->setChart(m_chart);// 将图表对象设置到graphicsView上进行显示
ui->graphicsView->setRenderHint(QPainter::Antialiasing);// 设置渲染:抗锯齿,如果不设置那么曲线就显得不平滑
}
PlotDialog::~PlotDialog()
{
delete ui;
}
void PlotDialog::qDebug_recv(float &plot_x,float &plot_y)
{
ui->lineEdit_X->setText(QString::number(plot_x));
ui->lineEdit_Y->setText(QString::number(plot_y));
// float plot_X = ui->lineEdit_X->text().toFloat();
// float plot_Y = ui->lineEdit_Y->text().toFloat();
if(plot_x > 10)
{
m_chart->axisX()->setMax(plot_x);
}
if(plot_y > 10)
{
m_chart->axisY()->setMax(plot_y);
}
m_lineSeries->append(QPointF(plot_x,plot_y));
}
3 主窗口设计
开始绘图按钮点击触发开启定时器和创建自定义对话框的槽函数,是周期为200ms的定时器回调函数里面对XY坐标进行数据更新,并触发含参信号,自定义对话框类收到坐标信息开始绘图。
widget.h文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTimer>
#include"plotdialog.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
//点击开始绘图按钮槽函数
void on_pBtnOpenDialog_clicked();
//定时器触发函数
void timerTimeout();
private:
Ui::Widget *ui;
//创建自定义对话框
PlotDialog *dialog;
//创建用于模拟生成实时数据的定时器
QTimer *my_timer;
//用于记录更新数据初值
int plot_number = 0;
signals:
//定义向自定义窗口发送的含参信号
void widgetEmit(float &,float &);
};
#endif // WIDGET_H
widget.cpp文件
#include "widget.h"
#include "ui_widget.h"
#include <QtMath>
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//实例化定时器对象
my_timer = new QTimer(this);
my_timer->setSingleShot(false);//默认是false,重复触发,可不设置;true模式是单次触发
connect(my_timer,&QTimer::timeout,this,&Widget::timerTimeout);
//自定义对话框实例化对象
dialog = new PlotDialog(this);
// connect(this,&Widget::widgetEmit,dialog,&PlotDialog::qDebug_recv);
connect(this,&Widget::widgetEmit,dialog,&PlotDialog::qDebug_recv);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pBtnOpenDialog_clicked()
{
dialog->setModal(false);
dialog->show();
//dialog->setAttribute(Qt::WA_DeleteOnClose);
//加上这句代码后在关闭dialog对话框时,再次点击开始绘图按钮后,对话框不会弹出,程序会异常结束。
//点击开始绘图按钮后,会同时开启定时器
if(my_timer->isActive())
{
my_timer->stop();
}else{
plot_number = 0;
my_timer->start(200);
}
}
void Widget::timerTimeout()
{
QString strValue = QString::number(plot_number);
ui->lineEdit_x->setText(strValue);
ui->lineEdit_y->setText(strValue);
float plot_x = ui->lineEdit_x->text().toFloat();
float plot_y = ui->lineEdit_y->text().toFloat();
//connect(this,&Widget::widgetEmit,dialog,&PlotDialog::qDebug_recv);
//链接建立在此处会导致重复链接,造成内存泄露,长时间画图会造成卡顿
emit widgetEmit(plot_x,plot_y);
plot_number++;
}
4动画演示
5 总结
这是我首次在CSDN上分享自己的学习经历,如果有什么不足之处请各位小伙伴批评指正,希望我的这篇文章对你有所帮助!!!