Updating Qt Line Series in Real-Time is not working
-
Hi Everyone,
I want to make a very simple application, where I am getting the data from Serial Port, and then I have to update this data on the Qt Line Chart in Real-Time.
Note: I am getting the data @ 1sec per data, so it's not so fast.
I can receive this data from the Serial port properly (checked using qDebug) message but it is not updated on the Qt Line Series Chart.The following is my public slot function, where I receive the Serial Data.
void TemperatureViewer::read_data() { char data; uint8_t temp_adc_count; QDateTime now; while( m_serial.bytesAvailable() ) { // Read one byte at a time m_serial.read(&data, 1); if( (data != '\r') && (data != '\n') ) { temp_adc_count = data; now = QDateTime::currentDateTime(); series->append( now.toMSecsSinceEpoch(), temp_adc_count ); qDebug() << temp_adc_count; // qDebug() << series; chartView->update(); } } }
So in the above function, I am appending the series with the current time on the x-axis and the value received on the Serial port on Y-Axis, and this is not working.
chartView->update();
even this function call is not doing anything.My Complete class code is as below.
#include "temperatureviewer.h" #include "./ui_temperatureviewer.h" #include <QtCharts/QChartView> #include <QtCharts/QLineSeries> #include <QtCore/QDateTime> #include <QtCharts/QDateTimeAxis> #include <QtCharts/QValueAxis> /* Chart Related Objects Starts */ QLineSeries *series; QChartView *chartView; // QChart *chart; /* Chart Related Objects Finished */ TemperatureViewer::TemperatureViewer(QWidget *parent) : QMainWindow(parent) , ui(new Ui::TemperatureViewer) { ui->setupUi(this); qDebug() << "Detecting Available Serial Ports"; QList<QSerialPortInfo> serial_port_infos = QSerialPortInfo::availablePorts(); for (const QSerialPortInfo &port_info : serial_port_infos ) { qDebug() << "Port:" << port_info.portName(); // Add these found com ports to the combo box ui->cb_COMP->addItem(port_info.portName()); } // Create a Line Series and the current time and value will be updated // when serial data is received series = new QLineSeries(); // Test Code Starts /* QDateTime now = QDateTime::currentDateTime(); series->append( now.toMSecsSinceEpoch(), 10 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 11 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 12 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 13 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 14 ); */ // Test Code Ends // Create a chart where we append this data QChart *chart = new QChart(); chart->legend()->hide(); chart->addSeries(series); // chart->createDefaultAxes(); chart->setTitle("Real Time Temperature Visualization"); // Formatting X Axis QDateTimeAxis *axisX = new QDateTimeAxis; // axisX->setTickCount(10); axisX->setFormat("hh:mm:ss"); axisX->setTitleText("Time"); // Setting Range of 1 day (need to take care of series also) // QDateTime now = QDateTime::currentDateTime(); // axisX->setRange( now.toMSecsSinceEpoch(), now.addDays(1).toMSecsSinceEpoch() ); chart->addAxis(axisX, Qt::AlignBottom); series->attachAxis(axisX); // Formatting Y-Axis QValueAxis *axisY = new QValueAxis; axisY->setLabelFormat("%i"); axisY->setTitleText("Temperature Value"); axisY->setRange( 0, 255 ); chart->addAxis(axisY, Qt::AlignLeft); series->attachAxis(axisY); // Setting the Chart View chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); chartView->setParent(ui->horizontalFrame); } TemperatureViewer::~TemperatureViewer() { if( m_serial.isOpen() ) { // if serial port is open close it m_serial.close(); } delete ui; } void TemperatureViewer::on_btn_ConnectDisconnect_clicked( void ) { // if false, we have to connect, else disconnect if( connect_status == false ) { qInfo() << "Connecting..."; m_serial.setBaudRate( QSerialPort::Baud9600 ); m_serial.setDataBits( QSerialPort::Data8 ); m_serial.setParity( QSerialPort::NoParity ); m_serial.setStopBits( QSerialPort::OneStop ); m_serial.setFlowControl( QSerialPort::NoFlowControl ); // Select the COM Port from Combo Box m_serial.setPortName( ui->cb_COMP->currentText() );; if( m_serial.open( QIODevice::ReadWrite ) ) { qDebug() << "Serial Port Opened Successfully"; m_serial.write("Hello World from Qt\r\n"); connect_status = true; ui->btn_ConnectDisconnect->setText("Disconnect"); // disable the combo box ui->cb_COMP->setEnabled(false); // Connect Signal and Slots connect(&m_serial, SIGNAL( readyRead() ), this, SLOT(read_data() ) ); } else { qDebug() << "Unable to open the Selected Serial Port" << m_serial.error(); } } else { qInfo() << "Disconnecting..."; // close the serial port m_serial.close(); connect_status = false; ui->btn_ConnectDisconnect->setText("Connect"); // Enable the combo box ui->cb_COMP->setEnabled(true); } } void TemperatureViewer::read_data() { char data; uint8_t temp_adc_count; QDateTime now; while( m_serial.bytesAvailable() ) { // Read one byte at a time m_serial.read(&data, 1); if( (data != '\r') && (data != '\n') ) { temp_adc_count = data; now = QDateTime::currentDateTime(); series->append( now.toMSecsSinceEpoch(), temp_adc_count ); qDebug() << temp_adc_count; // qDebug() << series; chartView->update(); } } }
I used the below-mentioned test code, in the above class and it works fine.
QDateTime now = QDateTime::currentDateTime(); series->append( now.toMSecsSinceEpoch(), 10 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 11 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 12 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 13 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 14 );
But the real-time update is not working.
Can someone please help in finding the issue? -
@xpress_embedo
I would start by replacing all the code to do with reading from the serial port by a simpleQTimer
slot plotting a point on the series. See if that works. Verify theseries->append(...)
is adding a point to the correct series. Then maybe you have QtCharts issue.@JonB Thank You for your response.
But I think found the problem and now it is working fine, as shown below.
I guess the problem was related to the time axis format.axisX->setFormat("hh:mm:ss"); axisX->setTitleText("Time"); // Setting Range of 1 day (need to take care of series also) QDateTime now = QDateTime::currentDateTime(); axisX->setRange( now.toMSecsSinceEpoch(), now.addDays(1).toMSecsSinceEpoch() );
I changed this to
axisX->setFormat("hh:mm:ss"); axisX->setTitleText("Time"); // Setting Range of 1 day (need to take care of series also) QDateTime now = QDateTime::currentDateTime(); axisX->setRange( now, now.addSecs(120) );
After this change, it is working fine.
I have another small doubt, why this area highlighted in black color is blank.
While in the UI file, it is covering the whole screen.
-
Hi Everyone,
I want to make a very simple application, where I am getting the data from Serial Port, and then I have to update this data on the Qt Line Chart in Real-Time.
Note: I am getting the data @ 1sec per data, so it's not so fast.
I can receive this data from the Serial port properly (checked using qDebug) message but it is not updated on the Qt Line Series Chart.The following is my public slot function, where I receive the Serial Data.
void TemperatureViewer::read_data() { char data; uint8_t temp_adc_count; QDateTime now; while( m_serial.bytesAvailable() ) { // Read one byte at a time m_serial.read(&data, 1); if( (data != '\r') && (data != '\n') ) { temp_adc_count = data; now = QDateTime::currentDateTime(); series->append( now.toMSecsSinceEpoch(), temp_adc_count ); qDebug() << temp_adc_count; // qDebug() << series; chartView->update(); } } }
So in the above function, I am appending the series with the current time on the x-axis and the value received on the Serial port on Y-Axis, and this is not working.
chartView->update();
even this function call is not doing anything.My Complete class code is as below.
#include "temperatureviewer.h" #include "./ui_temperatureviewer.h" #include <QtCharts/QChartView> #include <QtCharts/QLineSeries> #include <QtCore/QDateTime> #include <QtCharts/QDateTimeAxis> #include <QtCharts/QValueAxis> /* Chart Related Objects Starts */ QLineSeries *series; QChartView *chartView; // QChart *chart; /* Chart Related Objects Finished */ TemperatureViewer::TemperatureViewer(QWidget *parent) : QMainWindow(parent) , ui(new Ui::TemperatureViewer) { ui->setupUi(this); qDebug() << "Detecting Available Serial Ports"; QList<QSerialPortInfo> serial_port_infos = QSerialPortInfo::availablePorts(); for (const QSerialPortInfo &port_info : serial_port_infos ) { qDebug() << "Port:" << port_info.portName(); // Add these found com ports to the combo box ui->cb_COMP->addItem(port_info.portName()); } // Create a Line Series and the current time and value will be updated // when serial data is received series = new QLineSeries(); // Test Code Starts /* QDateTime now = QDateTime::currentDateTime(); series->append( now.toMSecsSinceEpoch(), 10 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 11 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 12 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 13 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 14 ); */ // Test Code Ends // Create a chart where we append this data QChart *chart = new QChart(); chart->legend()->hide(); chart->addSeries(series); // chart->createDefaultAxes(); chart->setTitle("Real Time Temperature Visualization"); // Formatting X Axis QDateTimeAxis *axisX = new QDateTimeAxis; // axisX->setTickCount(10); axisX->setFormat("hh:mm:ss"); axisX->setTitleText("Time"); // Setting Range of 1 day (need to take care of series also) // QDateTime now = QDateTime::currentDateTime(); // axisX->setRange( now.toMSecsSinceEpoch(), now.addDays(1).toMSecsSinceEpoch() ); chart->addAxis(axisX, Qt::AlignBottom); series->attachAxis(axisX); // Formatting Y-Axis QValueAxis *axisY = new QValueAxis; axisY->setLabelFormat("%i"); axisY->setTitleText("Temperature Value"); axisY->setRange( 0, 255 ); chart->addAxis(axisY, Qt::AlignLeft); series->attachAxis(axisY); // Setting the Chart View chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); chartView->setParent(ui->horizontalFrame); } TemperatureViewer::~TemperatureViewer() { if( m_serial.isOpen() ) { // if serial port is open close it m_serial.close(); } delete ui; } void TemperatureViewer::on_btn_ConnectDisconnect_clicked( void ) { // if false, we have to connect, else disconnect if( connect_status == false ) { qInfo() << "Connecting..."; m_serial.setBaudRate( QSerialPort::Baud9600 ); m_serial.setDataBits( QSerialPort::Data8 ); m_serial.setParity( QSerialPort::NoParity ); m_serial.setStopBits( QSerialPort::OneStop ); m_serial.setFlowControl( QSerialPort::NoFlowControl ); // Select the COM Port from Combo Box m_serial.setPortName( ui->cb_COMP->currentText() );; if( m_serial.open( QIODevice::ReadWrite ) ) { qDebug() << "Serial Port Opened Successfully"; m_serial.write("Hello World from Qt\r\n"); connect_status = true; ui->btn_ConnectDisconnect->setText("Disconnect"); // disable the combo box ui->cb_COMP->setEnabled(false); // Connect Signal and Slots connect(&m_serial, SIGNAL( readyRead() ), this, SLOT(read_data() ) ); } else { qDebug() << "Unable to open the Selected Serial Port" << m_serial.error(); } } else { qInfo() << "Disconnecting..."; // close the serial port m_serial.close(); connect_status = false; ui->btn_ConnectDisconnect->setText("Connect"); // Enable the combo box ui->cb_COMP->setEnabled(true); } } void TemperatureViewer::read_data() { char data; uint8_t temp_adc_count; QDateTime now; while( m_serial.bytesAvailable() ) { // Read one byte at a time m_serial.read(&data, 1); if( (data != '\r') && (data != '\n') ) { temp_adc_count = data; now = QDateTime::currentDateTime(); series->append( now.toMSecsSinceEpoch(), temp_adc_count ); qDebug() << temp_adc_count; // qDebug() << series; chartView->update(); } } }
I used the below-mentioned test code, in the above class and it works fine.
QDateTime now = QDateTime::currentDateTime(); series->append( now.toMSecsSinceEpoch(), 10 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 11 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 12 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 13 ); now = now.addSecs(1); series->append( now.toMSecsSinceEpoch(), 14 );
But the real-time update is not working.
Can someone please help in finding the issue?Can someone please provide some suggestions here?
-
Can someone please provide some suggestions here?
@xpress_embedo Qt Version and OS please?
-
@xpress_embedo Qt Version and OS please?
@JoeCFD I am using Qt 6.2.4 and the OS is Windows 10. (Project is configured for MinGW not Android)
Installation details from Qt Maintenance Tool
-
@JoeCFD I am using Qt 6.2.4 and the OS is Windows 10. (Project is configured for MinGW not Android)
Installation details from Qt Maintenance Tool
@xpress_embedo I would suggest you upgrade Qt version to Qt 6.4.3 or Qt 6.5.0 first. A lot of changes have been made in Qt6. Better to use the latest or close to the latest version.
-
@xpress_embedo I would suggest you upgrade Qt version to Qt 6.4.3 or Qt 6.5.0 first. A lot of changes have been made in Qt6. Better to use the latest or close to the latest version.
@JoeCFD Hmmm I thought the version I am using is LTS
Also with the same Qt Version, and instead of using QtCharts I used the QCustomPlot library and everything worked well, sample output is shown below.
I am just curious why my QtChart is not working fine, I am 100% sure it is my mistake, I need to spend more time on it.
-
@JoeCFD Hmmm I thought the version I am using is LTS
Also with the same Qt Version, and instead of using QtCharts I used the QCustomPlot library and everything worked well, sample output is shown below.
I am just curious why my QtChart is not working fine, I am 100% sure it is my mistake, I need to spend more time on it.
@xpress_embedo
I would start by replacing all the code to do with reading from the serial port by a simpleQTimer
slot plotting a point on the series. See if that works. Verify theseries->append(...)
is adding a point to the correct series. Then maybe you have QtCharts issue. -
@xpress_embedo
I would start by replacing all the code to do with reading from the serial port by a simpleQTimer
slot plotting a point on the series. See if that works. Verify theseries->append(...)
is adding a point to the correct series. Then maybe you have QtCharts issue.@JonB Thank You for your response.
But I think found the problem and now it is working fine, as shown below.
I guess the problem was related to the time axis format.axisX->setFormat("hh:mm:ss"); axisX->setTitleText("Time"); // Setting Range of 1 day (need to take care of series also) QDateTime now = QDateTime::currentDateTime(); axisX->setRange( now.toMSecsSinceEpoch(), now.addDays(1).toMSecsSinceEpoch() );
I changed this to
axisX->setFormat("hh:mm:ss"); axisX->setTitleText("Time"); // Setting Range of 1 day (need to take care of series also) QDateTime now = QDateTime::currentDateTime(); axisX->setRange( now, now.addSecs(120) );
After this change, it is working fine.
I have another small doubt, why this area highlighted in black color is blank.
While in the UI file, it is covering the whole screen.
-
@JonB Thank You for your response.
But I think found the problem and now it is working fine, as shown below.
I guess the problem was related to the time axis format.axisX->setFormat("hh:mm:ss"); axisX->setTitleText("Time"); // Setting Range of 1 day (need to take care of series also) QDateTime now = QDateTime::currentDateTime(); axisX->setRange( now.toMSecsSinceEpoch(), now.addDays(1).toMSecsSinceEpoch() );
I changed this to
axisX->setFormat("hh:mm:ss"); axisX->setTitleText("Time"); // Setting Range of 1 day (need to take care of series also) QDateTime now = QDateTime::currentDateTime(); axisX->setRange( now, now.addSecs(120) );
After this change, it is working fine.
I have another small doubt, why this area highlighted in black color is blank.
While in the UI file, it is covering the whole screen.
The real-Time Plot not working is already resolved above, and the blank chart area can be resolved by adding the following line.
chartView->setMinimumSize( ui->frame->size() );
-