Qt之QCustomPlot二次封装:根据时间轴变化的趋势图控件

前言

使用轻量级图表控件进行开发已经有一段时间了,最近接到一个需求,如何能够直观简约的标识一个变量随着时间的变化,相对于之前的几个控件还是比较简单的,可以直接拿去提升使用。

关键函数介绍

QCustomPlot的安装配置在我的这篇文章里有介绍,不再复述,直接介绍趋势图控件的关键代码。

InitAxis() : 坐标轴初始化函数

void TimeTrendShowForm::InitAxis(QString title,QString unit_name,int temp_tick_count, double max_count, QString time_format, int unit_second)
{
    value_title=title;
    value_unit_name=unit_name;

    ui->widget->graph(0)->setName(title+": 0");

    QSharedPointer<QCPAxisTickerDateTime> date_time_ticker(new QCPAxisTickerDateTime);

    date_time_ticker->setDateTimeFormat(time_format);

    tick_count=temp_tick_count;
    date_time_ticker->setTickCount(tick_count);
    date_time_ticker->setTickStepStrategy(QCPAxisTicker::tssMeetTickCount);

    ui->widget->xAxis->setTickLabelRotation(1);//刻度线稍微倾斜,节省空间,参数是角度

    ui->widget->xAxis->setTicker(date_time_ticker);

    //1秒作为单位刻度
    ui->widget->xAxis->setSubTickLength(1);

    ui->widget->xAxis2->setVisible(true);
    ui->widget->yAxis2->setVisible(true);
    ui->widget->xAxis2->setTickLabels(false);
    ui->widget->yAxis2->setTickLabels(false);
    ui->widget->xAxis2->setTicks(false);
    ui->widget->yAxis2->setTicks(false);
    ui->widget->xAxis2->setSubTicks(false);
    ui->widget->yAxis2->setSubTicks(false);

    max_show_count=max_count;

    one_unit_second=unit_second;
}

第一个参数是数据的标题,第二个是数据的单位,第三个是横坐标需要显示的大分格的个数,第四个则是能够显示的最大点,第四个变量是时间轴要显示的时间字符串的格式,第五个则是数据刷新频率(以秒为单位)。
我在Demo程序中的mainwindow构造函数调用了这个函数:

ui->widget->InitAxis("温度","℃",6,30,"hh:mm:ss",1);

图表的效果就出来了。Qt之QCustomPlot二次封装:根据时间轴变化的趋势图控件_第1张图片

AddOneValue(): 加入数据,让数据动起来

坐标轴初始化好了,就要写数据插入函数了,具体代码如下:

void TimeTrendShowForm::AddOneValue(double time_t,double data)
{
    bool max_value_change_flag=false;
    bool min_value_change_flag=false;

    int count_1;
    int count_2;

    value_list.time_t_vector.push_back(time_t);
    value_list.value_vector.push_back(data);

    count_1=value_list.time_t_vector.count();
    count_2=value_list.value_vector.count();

    if(count_1!=count_2)
    {
        value_list.time_t_vector.clear();
        value_list.value_vector.clear();
        return;
    }

    if(count_1>max_show_count)
    {
        value_list.time_t_vector.removeFirst();
        value_list.value_vector.removeFirst();
    }

    count_1=value_list.value_vector.count();

    if(count_1<=0)
    {
        return;
    }

    value_list.max_value=value_list.value_vector.at(0);
    value_list.min_value=value_list.value_vector.at(0);

    for(int i=0;i<count_1;i++)
    {
        if(value_list.max_value<value_list.value_vector.at(i))
        {
            max_value_change_flag=true;
            value_list.max_value=value_list.value_vector.at(i);
        }

        if(value_list.min_value>value_list.value_vector.at(i))
        {
            min_value_change_flag=true;
            value_list.min_value=value_list.value_vector.at(i);
        }
    }

    if(max_value_change_flag==true)
    {
        ui->widget->yAxis->setRangeUpper(value_list.max_value+1);
    }

    if(min_value_change_flag==true)
    {
        ui->widget->yAxis->setRangeLower(value_list.min_value-1);
    }

    ui->widget->xAxis->setRange(time_t-one_unit_second*max_show_count,time_t);

    ui->widget->graph(0)->setData(value_list.time_t_vector,value_list.value_vector);

    //把最新值刷在标题上
    QString temp_value_str=QString::number(data,'f',1);
    ui->widget->graph(0)->setName(value_title+": "+temp_value_str+value_unit_name);

    ui->widget->replot();
}

调用这个函数时要注意,调用频率一定要和初始化轴函数的最后一个参数相一致,比如在初始化时我填写的是1,那么AddOneValue函数就要一秒钟调用一次,每次调用,把最新的数值填进来。
我在Demo的mainwindow类中重新了timerEvent,然后设置了一个1秒钟的timer,周期到达时调用一次AddOneValue函数:

void MainWindow::timerEvent(QTimerEvent *event)
{
    if(event->timerId()==cycle_id)
    {
        unsigned int time_t=QDateTime::currentDateTime().toTime_t();

        double data=(double)(qrand()%500)/10-10;

        ui->widget->AddOneValue(time_t,data);
    }
}

重新编译一下,效果出来了:
Qt之QCustomPlot二次封装:根据时间轴变化的趋势图控件_第2张图片
大家可是试着改变一下背景色,我已经实现,有兴趣的可以交流。

你可能感兴趣的:(Qt之QCustomPlot二次封装:根据时间轴变化的趋势图控件)