6

QChart追加した に新しいポイントを追加した後にを再描画する方法を知りたいQLineSeriesです。 目標は、これを使用して、高速 (最大 400 000 ポイント/秒) で取得されたデータを表示し、ポイントがパケットで到着したときにプロットを更新することです。

これが私が取り組んできたテストプログラムです:

メインウィンドウ:

class MainWindow : public QMainWindow{
    Q_OBJECT

    QLineSeries *series;
    QChart *chart;
    QChartView *chartView;

    int cnt=0;


public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pB_Start_clicked();

private:
    Ui::MainWindow *ui;
};

MainWindow コンストラクター:

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){
    ui->setupUi(this);

    series = new QLineSeries();

    chart = new QChart();
    chart->setBackgroundRoundness(0);

    chart->addSeries(series);

 // A bunch of formatting
    chart->setBackgroundVisible(false);
    chart->setMargins(QMargins(0,0,0,0));
    chart->layout()->setContentsMargins(0,0,0,0);
    chart->legend()->hide();
    chart->setPlotAreaBackgroundBrush(QBrush(Qt::black));
    chart->setPlotAreaBackgroundVisible(true);
    chartView = new QChartView(chart);
    ui->gridLayout->addWidget(chartView);

}

そして、シリーズにポイントを追加するための pushButtonclickedイベント:

void MainWindow::on_pB_Start_clicked(){
    series->append(cnt,qSin(cnt/10));
    cnt++;
    // Update plot here << ======== HOW?
}

OpenGLSeries の例では、何らかの方法でそれを行います。方法がわかりません。ただし、その場合は、シリーズのすべてのポイントを追加するのではなく、新しいポイントに置き換えるため、少し異なります。

4

2 に答える 2

4

どうやら QCharts は必要ありませんrepaint()。シリーズに新しいポイントを追加するだけで十分なようです。文字の軸を設定していなかったため、また値が適切に計算されていなかったため、データが表示されませんでした。

修正されたコード:

ヘッダ:

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){
    ui->setupUi(this);

    series = new QLineSeries();

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

    chart->createDefaultAxes(); // Preparing the axis
    chart->axisX()->setRange(0,10); 
    chart->axisY()->setRange(0,10); 

    // Same formatting
    chart->setBackgroundVisible(false);
    chart->setMargins(QMargins(0,0,0,0));
    chart->layout()->setContentsMargins(0,0,0,0);
    chart->legend()->hide();
    chart->setPlotAreaBackgroundBrush(QBrush(Qt::black));
    chart->setPlotAreaBackgroundVisible(true);
    chartView = new QChartView(chart);
    ui->gridLayout->addWidget(chartView);
}

そして、計算前に double にキャストする pushButton コードcnt

void MainWindow::on_pB_Start_clicked(){
    double val = 3*(qSin((double)cnt*2)+2);
    series->append(cnt,val); // Enough to trigger repaint!
    cnt++;
}
于 2016-08-06T16:32:21.577 に答える
2

まず、GUI スレッドで 400000 ポイント/秒でポイントを受け取って追加すると、アプリケーションが完全にフリーズします。したがって、別のスレッドをデータの受信と処理専用にし、(たとえば) QueuedConnectionに接続されたシグナル/スロットを使用して、処理されたグラフィックス データを GUI スレッドに送信する必要があります。「処理」とは、少なくとも何らかのデシメーション (DSP 担当者が理解しているように、平均化、ドロップ、デシメーション) を意味します。400000 ポイント/秒は高速に見えるため、メモリと GUI のパフォーマンスが無駄になります。しかし、間引きしたくない場合は、あなた次第です。この場合、QueuedConnectioned シグナル/スロットよりも軽量なデータ配信メカニズムを検討できます。

2 番目の質問は、いつプロットするかです。少し前に、同様の機能をQCustomPlotはるかに低いレートで実装しました。私が直面した主な問題は、特にアンチエイリアスされたグラフをプロットしているときに、各ポイントを受け取った後に再プロットしようとしたときの巨大な (そしてさまざまな) 遅延でした。あなたの場合、解決策はサブクラス化QChartViewすることです(すでに行っていると思います)、それをオーバーライドし、再プロットを開始/停止する必要があるときに/timerEventを呼び出します。または、オブジェクトを所有するオブジェクトにタイマーを保持し、そこから再プロットを発行することもできますが、サブクラス化に比べて抽象化漏れのように見えます。全体として、このアプローチにより、ほぼ一定のフレームレートを実現し、アプリケーションのインターフェイスをフリーズさせることなく、必要なだけスムーズにすることができます。startTimer()killTimer()QChartViewQChartView

そして最後に、再プロットする方法は?必要なことを行うメソッドが継承されQChartViewているようです。repaint()QWidget

于 2016-08-06T14:24:04.733 に答える