找回密码
 立即注册
收起左侧

QCustomPlot之简单动态图(六)

0
回复
3943
查看
[复制链接]
累计签到:10 天
连续签到:1 天
来源: 原创 2020-3-21 21:11:33 显示全部楼层 |阅读模式

本章节是仿照echart的动态图:[地址]

一、设置布局

首先新增一行一列用于放置标题和图例,这里将图例放置在一个空的轴矩形当中--[QCustomPlot之层和布局(四)]

// setupDynamicData(QCustomPlot *customPlot) 函数中
customPlot->plotLayout()->insertRow(0);
customPlot->plotLayout()->insertColumn(0);

QCPAxisRect *legendRect = new QCPAxisRect(customPlot, false);  // 不需要配置轴,因为我们只是把图例放在这里
legendRect->setAutoMargins(QCP::msNone); // 不计算边距
legendRect->insetLayout()->addElement(customPlot->legend, Qt::AlignCenter);  // 放置图例
customPlot->legend->setVisible(true);
customPlot->legend->setFillOrder(QCPLayoutGrid::foColumnsFirst); // 横向图例

customPlot->axisRect()->setAutoMargins(QCP::msBottom | QCP::msRight); // 只计算下边距和右边距
customPlot->plotLayout()->addElement(0, 0, new QCPTextElement(customPlot, "动态数据", QFont("sans", 12, QFont::Bold)));
customPlot->plotLayout()->addElement(0, 1, legendRect);
customPlot->plotLayout()->setRowStretchFactor(0, 0.1);    // 让其尽可能小一点
customPlot->plotLayout()->setColumnStretchFactor(0, 0.1);

二、设置图表

其次添加一个柱状图和折线图,并且添加它们的数据,注意这里采用QCPAxisTickerText而不采用QCPAxisTickerTime或者QCPAxisTickerDateTime的原因,是因为我们不想要它们计算刻度线的位置,同时要注意让xAxis2保持与xAxis的联动,这里只需连接信号槽即可

// setupDynamicData(QCustomPlot *customPlot) 函数中
// 设置柱状图
QCPBars *bar = new QCPBars(customPlot->xAxis, customPlot->yAxis2);
bar->setName("预购队列");
bar->setPen(Qt::NoPen);
bar->setBrush(QColor(194, 53, 49));

// 设置折线图
QCPGraph *graph = customPlot->addGraph(customPlot->xAxis, customPlot->yAxis);
graph->setName("最新成交价");
graph->setPen(QPen(QColor(47, 69, 84), 2));
graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QColor(47, 69, 84), QColor(Qt::white), 4));

customPlot->yAxis->setLabel("价格");
customPlot->yAxis->setRange(0, 30);
customPlot->yAxis->setSubTicks(false);   // 设置子刻度线不显示
customPlot->yAxis->setTickLength(0, 6);  // 设置刻度线内外的长度
customPlot->yAxis2->setLabel("预购量");
customPlot->yAxis2->setVisible(true);
customPlot->yAxis2->setRange(0, 1200);
customPlot->yAxis2->setSubTicks(false);
customPlot->yAxis2->setTickLength(0, 6);

// 这里之所以用 QCPAxisTickerText,而不用 QCPAxisTickerTime / QCPAxisTickerDateTime 是因为它们会自动计算刻度线的位置,这是我们不想要的
QSharedPointer<QCPAxisTickerText> timeTicker(new QCPAxisTickerText);
QSharedPointer<QCPAxisTickerText> indexTicker(new QCPAxisTickerText);
customPlot->xAxis->setTicker(timeTicker);
customPlot->xAxis->setSubTicks(false);
customPlot->xAxis2->setVisible(true);
customPlot->xAxis2->setSubTicks(false);
customPlot->xAxis2->setTicker(indexTicker);
connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange)));  // 重要:让xAxis2与xAxis保持联动

// 添加数据
QVector<double> datax, datay1, datay2;
QTime now = QTime::currentTime();
for (int i = 0; i < 8; ++i) {
    mLabels.insert(0, now.toString("hh:mm:ss"));  // mLabels == QVector<QString>
    datax.insert(0, now.msecsSinceStartOfDay() / 1000.0);  // 时间
    now = now.addMSecs(-2000);

    mIndexLabels.insert(0, QString::number(8 - i));
    datay1.insert(0, QRandomGenerator::global()->bounded(20) + 5);   // 产生随机数,Qt 5.10 以下用qrand() % 20
    datay2.insert(0, QRandomGenerator::global()->bounded(1000));
}

mIndex = 8;
mPositions = datax; // mPositions == QVector<double>

graph->setData(datax, datay1);
bar->setData(datax, datay2);

timeTicker->setTicks(mPositions, mLabels);   // 设置刻度线位置和刻度标签
indexTicker->setTicks(mPositions, mIndexLabels);

customPlot->xAxis->rescale();
customPlot->xAxis->scaleRange(1.1);  // 稍微缩放一下,以显示全部

三、连接计时信号槽

// setupDynamicData(QCustomPlot *customPlot) 函数中
connect(&dataTimer, SIGNAL(timeout()), this, SLOT(dynamicDataSlot()));
dataTimer.start(2000);  // 2秒刷新一次

四、设置数据刷新的槽函数

以下都是在dynamicDataSlot槽函数中

  • 去除之前的数据
QCPBars *bar = static_cast<QCPBars *>(ui->customPlot->plottable(0));

// 移除第一个数据
bar->data()->remove(mPositions.first());
ui->customPlot->graph(0)->data()->remove(mPositions.first());

mPositions.removeFirst();
mLabels.removeFirst();
mIndexLabels.removeFirst();
  • 添加新增数据
// 计算当前时间
double key = QTime::currentTime().msecsSinceStartOfDay() / 1000.0;
QString label = QTime::currentTime().toString("hh:mm:ss");

ui->customPlot->graph(0)->addData(key, QRandomGenerator::global()->bounded(20) + 5);
bar->addData(key, QRandomGenerator::global()->bounded(1000));

mPositions.push_back(key);
mLabels.push_back(label);
mIndexLabels.push_back(QString::number(++mIndex));
  • 重新设置轴并刷新图表
QCPAxisTickerText *timeTicker = static_cast<QCPAxisTickerText *>(ui->customPlot->xAxis->ticker().data());
timeTicker->setTicks(mPositions, mLabels);  // 重新设置x轴

QCPAxisTickerText *indexTicker = static_cast<QCPAxisTickerText *>(ui->customPlot->xAxis2->ticker().data());
indexTicker->setTicks(mPositions, mIndexLabels);

ui->customPlot->xAxis->rescale();
ui->customPlot->xAxis->scaleRange(1.1);

ui->customPlot->replot();

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了