使用轻量级图表控件进行开发已经有一段时间了,最近接到一个需求,如何能够直观简约的标识一个变量随着时间的变化,相对于之前的几个控件还是比较简单的,可以直接拿去提升使用。
QCustomPlot的安装配置在我的这篇文章里有介绍,不再复述,直接介绍趋势图控件的关键代码。
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);
坐标轴初始化好了,就要写数据插入函数了,具体代码如下:
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);
}
}