Real-time update of QChart
-
I am receiving a string over a bluetooth connection which contains values from 3 different sensors. I am using Qchart (bars) to display incoming data.
How can I update the QChart without flickering the display (smooth data update)? Because so far I have managed to display incoming data but the display is flickering every time it updates the value.
-
@closx sure, this is the code: ```
#include "mainwindow1.h"
#include "ui_mainwindow1.h"
#include<QtBluetooth>
#include<QBluetoothSocket>
#include <QTimer>#include <QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QBarSeries>
#include <QtCharts/QBarSet>
#include <QtCharts/QLegend>
#include <QtCharts/QBarCategoryAxis>
#include <QtCharts/QHorizontalStackedBarSeries>
#include <QtCharts/QLineSeries>
#include <QtCharts/QCategoryAxis>
#include <QtCharts/QPieSeries>
#include <QtCharts/QPieSlice>QT_CHARTS_USE_NAMESPACE
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent){
//Chart Display
// chartDisp();// Turn Bluetooth on localDevice.powerOn(); connect(agent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), this, SLOT(deviceDiscovered(QBluetoothDeviceInfo))); //connect(this, &MainWindow::messageReceived,this, &MainWindow::showMessage); agent->start(); socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); readSocket(); /********Run Timer to Recieve Bluetooth Data**********/ timer = new QTimer(this); timer1 = new QTimer(this); //connect(timer, &QTimer::timeout, contextObj, []{/* your code here */}); connect(timer, SIGNAL(timeout()),this, SLOT(readSocket())); connect(timer, SIGNAL(timeout()),this, SLOT(socketStatuscheck())); connect(timer1, SIGNAL(timeout()),this, SLOT(chartDisp())); timer->start(50); timer->start(1000); /*-----------------------------------------------------*/
}
MainWindow::~MainWindow()
{
}//****************************************************************************
void MainWindow::deviceDiscovered(const QBluetoothDeviceInfo &device)
{
//ui->listWidget->addItem(device.address().toString());
//ui->listWidget->addItem(device.name());static const QString serviceUuid(QStringLiteral("00001101-0000-1000-8000-00805F9B34FB")); socket->connectToService(QBluetoothAddress("20:19:03:29:27:62"), QBluetoothUuid(serviceUuid), QIODevice::ReadWrite);
}
//****************************************************************************
void MainWindow::readSocket()
{
//QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender());
// if (!socket)
// return;while (socket->canReadLine()) { QByteArray line = socket->readLine().trimmed(); emit messageReceived(socket->peerName(), QString ::fromUtf8(line.constData(), line.length())); QStringList lista, listc, listd; QString listb= QString::fromUtf8(line.constData(), line.length()); lista= listb.split(","); listc=lista.at(2).split("@"); listd=listc.at(1).split("~");
//****************************************************************
a=lista.at(1).toInt();
b=listc.at(0).toInt();
c=listd.at(0).toInt();
//*****************************************************************
QString result;
result.append(lista.at(1));
result.append("\n");
result.append(listc.at(0));
result.append("\n");
result.append(listd.at(0));
}
}
//****************************************************************************
void MainWindow::chartDisp()
{// Assign names to the set of bars used QBarSet *set0 = new QBarSet("Sensor 1"); QBarSet *set1 = new QBarSet("Sensor 2"); QBarSet *set2 = new QBarSet("Sensor 3"); // Assign values for each bar *set0 << a; *set1 << b; *set2 << c; // Add all sets of data to the chart as a whole // 1. Bar Chart QBarSeries *series = new QBarSeries(); // 2. Stacked bar chart // QHorizontalStackedBarSeries *series = new QHorizontalStackedBarSeries(); series->append(set0); series->append(set1); series->append(set2); // Used to define the bar chart to display, title // legend, QChart *chart = new QChart(); // Add the chart chart->addSeries(series); // Set title chart->setTitle("Sensor Values"); // Define starting animation // NoAnimation, GridAxisAnimations, SeriesAnimations chart->setAnimationOptions(QChart::NoAnimation); // Holds the category titles QStringList categories; categories << "2013"; // Adds categories to the axes QBarCategoryAxis *axis = new QBarCategoryAxis(); axis->append(categories); chart->createDefaultAxes(); // 1. Bar chart chart->setAxisX(axis, series); // 2. Stacked Bar chart // chart->setAxisY(axis, series); // Define where the legend is displayed chart->legend()->setVisible(true); chart->legend()->setAlignment(Qt::AlignBottom); // Used to display the chart QChartView *chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); // Used to change the palette QPalette pal = qApp->palette(); // Change the color around the chart widget and text pal.setColor(QPalette::Window, QRgb(0xffffff)); pal.setColor(QPalette::WindowText, QRgb(0x404044)); // Apply palette changes to the application qApp->setPalette(pal); setCentralWidget(chartView); resize(720,1060);
}
//****************************************************************************
void MainWindow::socketStatuscheck()
{
int socketState = socket->state();if (socketState==QAbstractSocket::ConnectedState) {
// ui->label_status->setText("Connected");
readSocket();
chartDisp();
}
else if(socketState==QAbstractSocket::UnconnectedState)
{
// Turn Bluetooth on
localDevice.powerOn();
// ui->label_status->setText("DisConnected");
agent->stop();
agent->start();
}}
-
@ahsan737 I see in your code, every time that timer changes, it triggers the function chartDisp(). And inside the chartDisp(), you add almost all of your components to the UI. So, this code makes your whole UI refresh (i can say) continuously. To avoid that, you must put the UI component creators (almostly all of your codes inside this function) to the outside (in your main constructor of your class). Only the component that you want to refresh continuously must be changing by the change of time.
It would be better if you create a widget just for the component that you want to refresh. You create the widget (lets say with the name myWidget) and include the component inside this widget. And inside the chartDisp() function, to update the widget, you can write;myWidget.update();
I guess this should work. If wont, post again and we can look for it deeper.
-
@ahsan737
Hello,#include "mainwindow1.h" #include "ui_mainwindow1.h" #include<QtBluetooth> #include<QBluetoothSocket> #include <QTimer> #include <QApplication> #include <QtWidgets/QMainWindow> #include <QtCharts/QChartView> #include <QtCharts/QBarSeries> #include <QtCharts/QBarSet> #include <QtCharts/QLegend> #include <QtCharts/QBarCategoryAxis> #include <QtCharts/QHorizontalStackedBarSeries> #include <QtCharts/QLineSeries> #include <QtCharts/QCategoryAxis> #include <QtCharts/QPieSeries> #include <QtCharts/QPieSlice> QT_CHARTS_USE_NAMESPACE MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { localDevice.powerOn(); connect(agent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), this, SLOT(deviceDiscovered(QBluetoothDeviceInfo))); agent->start(); socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); readSocket(); timer = new QTimer(this); timer1 = new QTimer(this); connect(timer, SIGNAL(timeout()),this, SLOT(readSocket())); connect(timer, SIGNAL(timeout()),this, SLOT(socketStatuscheck())); connect(timer1, SIGNAL(timeout()),this, SLOT(chartDisp())); timer->start(50); timer->start(1000); QBarSet *set0 = new QBarSet("Sensor 1"); QBarSet *set1 = new QBarSet("Sensor 2"); QBarSet *set2 = new QBarSet("Sensor 3"); *set0 << a; *set1 << b; *set2 << c; QBarSeries *series = new QBarSeries(); series->append(set0); series->append(set1); series->append(set2); QChart *chart = new QChart(); chart->addSeries(series); chart->setTitle("Sensor Values"); chart->setAnimationOptions(QChart::NoAnimation); QStringList categories; categories << "2013"; QBarCategoryAxis *axis = new QBarCategoryAxis(); axis->append(categories); chart->createDefaultAxes(); chart->setAxisX(axis, series); chart->legend()->setVisible(true); chart->legend()->setAlignment(Qt::AlignBottom); QChartView *chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); QPalette pal = qApp->palette(); pal.setColor(QPalette::Window, QRgb(0xffffff)); pal.setColor(QPalette::WindowText, QRgb(0x404044)); qApp->setPalette(pal); setCentralWidget(chartView); resize(720,1060); } MainWindow::~MainWindow() { } void MainWindow::deviceDiscovered(const QBluetoothDeviceInfo &device) { static const QString serviceUuid(QStringLiteral("00001101-0000-1000-8000-00805F9B34FB")); socket->connectToService(QBluetoothAddress("20:19:03:29:27:62"), QBluetoothUuid(serviceUuid), QIODevice::ReadWrite); } void MainWindow::readSocket() { while (socket->canReadLine()) { QByteArray line = socket->readLine().trimmed(); emit messageReceived(socket->peerName(), QString ::fromUtf8(line.constData(), line.length())); QStringList lista, listc, listd; QString listb= QString::fromUtf8(line.constData(), line.length()); lista= listb.split(","); listc=lista.at(2).split("@"); listd=listc.at(1).split("~"); a=lista.at(1).toInt(); b=listc.at(0).toInt(); c=listd.at(0).toInt(); QString result; result.append(lista.at(1)); result.append("\n"); result.append(listc.at(0)); result.append("\n"); result.append(listd.at(0)); } } void MainWindow::chartDisp() { charView.update(); //or charView.repaint(); } void MainWindow::socketStatuscheck() { int socketState = socket->state(); if (socketState==QAbstractSocket::ConnectedState) { readSocket(); chartDisp(); } else if(socketState==QAbstractSocket::UnconnectedState) { localDevice.powerOn(); agent->stop(); agent->start(); } }
Maybe something like that may work. Since I dont have qt charts module, I cannot test. I don't have much experience with charts too. You have to use the charts?
-
@closx thank you. I do not necessarily have to use Qcharts. If there is any other option to display data then I will simply opt that. I want to display incoming sensor values with a bar graph and plot them real-time. The required Bar graph (bars color is green, and it turns red when incoming sensor value is above a threshold value) and Line graphs are shown in images attached.