Я хотел бы знать, как перекрасить QChart
после того, как я добавляю новые пункты к QLineSeries
добавил к этому.
Цель состоит в том, чтобы использовать это для отображения данных, получаемых с высокой скоростью (до 400 000 точек / сек), и обновления графика по мере поступления точек в пакетах.
Вот тестовая программа, над которой я работал:
MainWindow:
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);
}
И кнопка clicked
Событие для добавления очков в серию:
void MainWindow::on_pB_Start_clicked(){
series->append(cnt,qSin(cnt/10));
cnt++;
// Update plot here << ======== HOW?
}
Пример OpenGLSeries делает это как-то. Я не понимаю как. Но в этом случае все немного по-другому, поскольку он заменяет все точки в серии новыми, а не добавляет их.
Во-первых, если вы получите и добавите очки со скоростью 400000 очков / сек в потоке графического интерфейса, ваше приложение будет полностью заморожено. Таким образом, вам необходимо выделить другой поток для получения и обработки данных и отправить обработанные графические данные в поток GUI, используя (например) сигналы / слоты, связанные с QueuedConnection. Под «обработкой» я подразумеваю, по крайней мере, некоторую децимацию (усреднение, отбрасывание, децимацию, как это понимают те, кто занимается DSP), поскольку скорость 400000 pts / sec, скорее всего, приведет к потере памяти и производительности графического интерфейса. Но если вы не хотите уничтожать, это ваше дело. В этом случае вы можете рассмотреть более легкий механизм доставки данных, чем QueuedConnection
Ed сигналы / слоты.
Второй вопрос: когда строить сюжет? Не так давно я реализовал похожую функциональность с QCustomPlot
по гораздо более низким ставкам. Основная проблема, с которой я столкнулся, заключалась в огромном (и меняющемся) лаге, когда я пытался реплотировать после получения каждой точки, особенно при построении графика сглаживания. В вашем случае решение заключается в подклассе QChartView
(Я полагаю, вы уже сделали это), переопределить timerEvent
в это и звони startTimer()
/killTimer()
когда вам нужно начать / остановить реплоттинг. Кроме того, вы можете держать таймер в объекте, который владеет QChartView
откладывание объектов и проблем оттуда, но это похоже на утечку абстракции по сравнению с подклассами QChartView
, В целом, этот подход позволяет вам достичь почти постоянной частоты кадров и сделать ее настолько плавной, насколько вы хотите, без зависания интерфейса приложения.
И, наконец, как сделать реплот? QChartView
кажется, имеет repaint()
метод, унаследованный от QWidget
который делает то, что вам нужно.
Видимо 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);
}
И код кнопки, кастинг cnt
удвоить до расчета.
void MainWindow::on_pB_Start_clicked(){
double val = 3*(qSin((double)cnt*2)+2);
series->append(cnt,val); // Enough to trigger repaint!
cnt++;
}