解决QCustomPlot长时间画实时曲线时总是曲线消失问题
盯了一天后,发现只要跨夜,曲线就会消失,经过查询资料可知,代码中使用 QTime::currentTime().msecsSinceStartOfDay() 来获取时间作为 x 轴的值,该方法返回的是从当天零点开始到当前时刻的毫秒数。当跨夜时,msecsSinceStartOfDay() 会重新从 0 开始计时,这就导致 x 轴的值会突然变小,进而使得之前绘制的曲线因为超出当前 x 轴显示范围而消失。
原部分代码
qint64 currentTime = QTime::currentTime().msecsSinceStartOfDay() / 1000.0;
double key = currentTime;
static double lastPointKey = 0;
double xMin = ui->customPlot->xAxis->range().lower;
double xMax = ui->customPlot->xAxis->range().upper;
upperLine->point1->setCoords(xMin, global::canshu[4].toDouble());
upperLine->point2->setCoords(xMax, global::canshu[4].toDouble());
downLine->point1->setCoords(xMin, global::canshu[3].toDouble());
downLine->point2->setCoords(xMax, global::canshu[3].toDouble());
更改后的代码:
void mainUI::initForm()
{
ui->customPlot->addGraph();
originalColor = QColor(qSin(2 * 1 + 1.2) * 80 + 80, qSin(2 * 0.3 + 0) * 80 + 80, qSin(2 * 0.3 + 1.5) * 80 + 80);
ui->customPlot->graph(0)->setPen(QPen(originalColor));
ui->customPlot->graph(0)->setLineStyle((QCPGraph::LineStyle)1);
ui->customPlot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 5));
// 添加上下限报警线
upperLine = new QCPItemStraightLine(ui->customPlot);
upperLine->setPen(QPen(Qt::red, 1, Qt::DashLine));
downLine = new QCPItemStraightLine(ui->customPlot);
downLine->setPen(QPen(Qt::red, 1, Qt::DashLine));
// 关键更改
QSharedPointer<QCPAxisTickerDateTime> timeTicker(new QCPAxisTickerDateTime);
// 关键更改
timeTicker->setDateTimeFormat("HH:mm:ss");
ui->customPlot->xAxis->setTicker(timeTicker);
ui->customPlot->axisRect()->setupFullAxesBox();
ui->customPlot->xAxis->setLabel("时间");
ui->customPlot->yAxis->setLabel("流量m³/s");
// 整个折线图标题
QCPTextElement* PlotTitle = new QCPTextElement(ui->customPlot, "日期-流量实时曲线图");
PlotTitle->setFont(QFont("宋体", 12, QFont::Bold)); // 设置标题的字体
ui->customPlot->plotLayout()->insertRow(0);
ui->customPlot->plotLayout()->addElement(0, 0, PlotTitle);
connect(ui->customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->customPlot->xAxis2, SLOT(setRange(QCPRange)));
connect(ui->customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->customPlot->yAxis2, SLOT(setRange(QCPRange)));
connect(&plotTimer, SIGNAL(timeout()), this, SLOT(realtimeDataSlot()));
}
void mainUI::realtimeDataSlot()
{
// 关键更改
long long currentTime = QDateTime::currentMSecsSinceEpoch() / 1000.0;
double key = currentTime;
static double lastPointKey = 0;
double xMin = ui->customPlot->xAxis->range().lower;
double xMax = ui->customPlot->xAxis->range().upper;
upperLine->point1->setCoords(xMin, global::canshu[4].toDouble());
upperLine->point2->setCoords(xMax, global::canshu[4].toDouble());
downLine->point1->setCoords(xMin, global::canshu[3].toDouble());
downLine->point2->setCoords(xMax, global::canshu[3].toDouble());
if (global::canshu[2]=="枯水期" && global::liuliang00 < global::canshu[3].toDouble())
{
ui->customPlot->graph(0)->setPen(QPen(Qt::red));
}
else if (global::canshu[2]=="丰水期" && global::liuliang00 < global::canshu[4].toDouble())
{
ui->customPlot->graph(0)->setPen(QPen(Qt::red));
}
else
{
ui->customPlot->graph(0)->setPen(QPen(originalColor));
}
// 两秒绘制一次数据
if (key - lastPointKey >= 2)
{
ui->customPlot->graph(0)->addData(currentTime, global::liuliang00);
recentData.append(global::liuliang00);
if (recentData.size() > dataCount)
{
recentData.removeFirst();
}
lastPointKey = key;
}
// 动态调整纵坐标
if (!recentData.isEmpty())
{
double minY = *std::min_element(recentData.begin(), recentData.end());
double maxY = *std::max_element(recentData.begin(), recentData.end());
double margin = qMax((maxY - minY) * 0.1, 0.1);
static double lastMinY = 0.0, lastMaxY = 0.0;
if (qAbs(minY - lastMinY) > 0.01 || qAbs(maxY-lastMaxY) > 0.01)
{
ui->customPlot->yAxis->setRange(minY - margin, maxY + margin);
lastMinY = minY;
lastMaxY = maxY;
}
}
ui->customPlot->xAxis->setRange(key, 8, Qt::AlignRight);
ui->customPlot->replot(QCustomPlot::rpQueuedReplot);
}