Qt | 采用自定义对话框实现对主窗口数据的实时画图

 前言

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上分享自己的学习经历,如果有什么不足之处请各位小伙伴批评指正,希望我的这篇文章对你有所帮助!!! 

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值