0

我有这段代码,它适用于高达 1000 的数据大小。现在我用 65536 点对其进行了测试。

series = new QLineSeries();

QList<QPointF> points;
points.reserve(data.size());

for(std::vector<int>::size_type i = 0; i != data.size(); i++) {
    QPointF point(i, data[i]*100/max);
    points.append(point);
}
series->clear();
series->append(points);

并且应用程序在 1 个核心全功率下冻结。几分钟后我停止了它。

如何防止 Qt 变得无响应。这个数据大小并不特殊,我希望图表视图可以处理多达百万点的数据集。

编辑:我测量了时间

series->append(points);

2000分需要1秒。这意味着大约一分钟 > 50.000 这是不可用的。

更糟糕的是,对数比例图

serieslog->append(points);

2000分需要40秒。那是完全无法使用的。原因是调试消息,几乎每个点都会打印出来。

QtCharts::XLogYDomain::calculateGeometryPoints(const QVector&) const>; 零和负值的对数未定义。

我可以加快线性情节

 series->setUseOpenGL(true);

但是对于 65536,它仍然需要 14 秒,这意味着每个点需要 200 µs。还是太多了。我想要一个最低 10 Hz 的实时视频和一个实时直方图。时间必须 << 1 秒。

编辑:这是一个工作示例,使用我的代码

#include <QDebug>
#include <QTime>
#include <cmath>
#include <stdlib.h>

#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QtCharts/QLogValueAxis>
#include <QtCharts/QValueAxis>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>

QT_CHARTS_USE_NAMESPACE

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QLineSeries * series;
    QLineSeries * serieslog;
    QChart * chart;
    QChartView * chartView;
    QValueAxis * axisX;
    QValueAxis * axisY;
    QLogValueAxis * axisY3;


    chart = new QChart();
    chart->legend()->hide();
    chart->setTitle("Histogramm");

    axisX = new QValueAxis;
    chart->addAxis(axisX, Qt::AlignBottom);

    series = new QLineSeries;
    chart->addSeries(series);

    axisY = new QValueAxis;
    axisY->setTitleText("linear scale");
    axisY->setLinePenColor(series->pen().color());
    axisY->setGridLinePen((series->pen()));

    chart->addAxis(axisY, Qt::AlignLeft);
    series->attachAxis(axisX);
    series->attachAxis(axisY);

    serieslog = new QLineSeries;
    chart->addSeries(serieslog);

    axisY3 = new QLogValueAxis();
    axisY3->setTitleText("logarithmic scale");
    axisY3->setLabelFormat("%g");
    axisY3->setLinePenColor(serieslog->pen().color());
    axisY3->setGridLinePen((serieslog->pen()));
    axisY3->setMinorTickCount(-1);

    chart->addAxis(axisY3, Qt::AlignRight);
    serieslog->attachAxis(axisX);
    serieslog->attachAxis(axisY3);

    chartView = new QChartView(chart);
    chartView->setRenderHint(QPainter::Antialiasing);

    // create data

    std::vector<int> data;
    int N = 10000;
    data.resize(N);
    for (int i=0; i < N; ++i){
        int value = static_cast<int>(fabs((sin(static_cast<double>(i)/1000.0)+1)*1+ std::rand() % 100)+10);
        data[i] = value;
    }

    QList<QPointF> points;
    points.reserve(data.size());

    for(std::vector<int>::size_type i = 0; i != data.size(); i++) { //
        QPointF point(i, data[i]);
        points.append(point);
    }
    QTime myTimer;
    myTimer.start();

    series->clear();
//    series->setUseOpenGL(true);
    series->append(points);
    qDebug() << "seconds lin: " << myTimer.elapsed();
    myTimer.start();
    serieslog->clear();
    serieslog->append(points);
    qDebug() << "seconds log: " << myTimer.elapsed();

    chart->axisX()->setRange(0, data.size());
    chart->axisY()->setRange(-10, 250);

    QMainWindow window;
    window.setCentralWidget(chartView);
    window.resize(800, 600);
    window.show();

    return app.exec();
}


QT += core
QT += widgets
QT += gui
QT += charts

SOURCES += \
    main.cpp

我测量毫秒 lin:1624 毫秒日志:6801

4

2 回答 2

2

我可以重现该问题(经过类似的经过时间),这似乎是QXYSeries::append处理方式的问题QList。从代码...

void QXYSeries::append(const QList<QPointF> &points)
{
    foreach (const QPointF &point , points)
        append(point);
}

和...

void QXYSeries::append(const QPointF &point)
{
    Q_D(QXYSeries);

    if (isValidValue(point)) {
        d->m_points << point;
        emit pointAdded(d->m_points.count() - 1);
    }
}

因此,每个点添加都可能导致QVector d->m_points调整大小并pointAdded发出信号。

鉴于您在调用之前清除了与该系列相关的所有数据,QXYSeries::append您可以使用它QXYSeries::replace

如果您必须生成初始数据,QList那么只需使用...

series->replace(points);

但是,在内部使用,QList::toVector所以如果您可以生成数据,QVector那就更好了......

QVector<QPointF> points(data.size());

for(std::vector<int>::size_type i = 0; i != data.size(); ++i) {
  points[i] = QPointF(i, data[i]);
}

QTime myTimer;
myTimer.start();

series->replace(points);
qDebug() << "\nlin: " << myTimer.elapsed() << "ms\n";

myTimer.start();
serieslog->replace(points);
qDebug() << "\nlog: " << myTimer.elapsed() << "ms\n";

我自己系统上的上述代码导致...

lin:  1 ms
log:  3 ms

10k点,100k点...

lin:  6 ms
log:  22 ms
于 2018-09-14T14:59:19.510 回答
0

我也注意到了这种缓慢,就我而言,我清除并替换了系列中的数据。我正在使用 QML。

当我在清除和附加新数据之前将系列设置为不可见,并在设置最小值和最大值等之后将其设置回可见时,我的性能得到了显着提升。

于 2021-08-30T04:42:45.630 回答