Unsolved On going data from TCP Server to a graph in the UI how do i do it?
-
How do i plot the data from the tcp server? I am able to plot a graph however i do not know how to do it with an ongoing data
//create charts
QChartView *chartView; //All charts initialize here. hs_ch1_raw_chart = new QChart(); hs_ch1_fft_chart = new QChart(); hs_ch2_raw_chart = new QChart(); hs_ch2_fft_chart = new QChart(); //Init init_LineChart(hs_ch1_raw_chart, "High Speed Channel 1 - RAW"); init_LineChart(hs_ch1_fft_chart, "High Speed Channel 1 - FFT"); init_LineChart(hs_ch2_raw_chart, "High Speed Channel 2 - RAW"); init_LineChart(hs_ch2_fft_chart, "High Speed Channel 2 - FFT"); chartView = new QChartView(hs_ch1_raw_chart); m_ui->gridLayout->addWidget(chartView, 1, 0); m_charts << chartView; chartView = new QChartView(hs_ch1_fft_chart); // Funny things happen if the pie slice labels do not fit the screen, so we ignore size policy chartView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); m_ui->gridLayout->addWidget(chartView, 1, 1); m_charts << chartView; //![5]
// chartView = new QChartView(createLineChart());
// m_ui->gridLayout->addWidget(chartView, 1, 2);
// //![5]
// m_charts << chartView;chartView = new QChartView(hs_ch2_raw_chart); m_ui->gridLayout->addWidget(chartView, 2, 0); m_charts << chartView; chartView = new QChartView(hs_ch2_fft_chart); m_ui->gridLayout->addWidget(chartView, 2, 1); m_charts << chartView;
void ThemeWidget::init_LineChart(QChart *chart, QString ChartName) const
{
chart->setTitle(ChartName);QString name("Series "); int nameIndex = 0; for (const DataList &list : m_dataTable) { QLineSeries *series = new QLineSeries(chart); for (const Data &data : list) series->append(data.first); series->setName(name + QString::number(nameIndex)); nameIndex++; chart->addSeries(series); } chart->createDefaultAxes(); chart->axes(Qt::Horizontal).first()->setRange(0, m_valueMax); chart->axes(Qt::Vertical).first()->setRange(0, m_valueCount); // Add space to label to add space between labels and axis QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first()); Q_ASSERT(axisY); axisY->setLabelFormat("%.1f ");
-
@DemonLord said in On going data from TCP Server to a graph in the UI how do i do it?:
i do not know how to do it with an ongoing data
Depends on what kind of chart you want. With X/Y chart you append new data via https://doc.qt.io/qt-5/qxyseries.html#append-1
So, what exactly is your question? -
It is non-trivial. Because you choose TCP the data received is stream data so may not arrive as granular datapoints. If you chose UDP then you could code so that each dgram contains a fixed number of datapoints. For TCP you need to intelligently parse the stream and pass the datapoint to the graph only when a complete datapoint has been received.
-
@Kent-Dorfman Don't forget that UDP does not offer the same guarantees with regard to data integrity than TCP so even if only full data points are transmitted some may be lost.
-
@Kent-Dorfman how do i parse the stream and pass the datapoint to the graph only when a complete datapoint has been received. Any tutorials or steps provided wil help alot
-
@DemonLord said in On going data from TCP Server to a graph in the UI how do i do it?:
how do i parse the stream and pass the datapoint to the graph only when a complete datapoint has been received
You need to define a protocoll. So you know when you got complete data packet.
-
@jsulm like this?
connect(chart,SIGNAL(tcpDataGUI(QByteArray&data)),this,SLOT(parseData(QByteArray))); // TcpDaraGUI was emitted after the data was converted from string to ascii,the parseData is a function on the UI
void ThemeWidget::parseData(QByteArray &data)
{
qDebug()<< "Got Data:" << data;
QJsonParseError parseError;
QJsonDocument jsonResponse = QJsonDocument::fromJson(data,&parseError);if(parseError.error != QJsonParseError::NoError) { qDebug()<< "Parse Error" <<parseError.errorString(); return; } QJsonArray jsonArray =jsonResponse.array(); if(!jsonArray.isEmpty()) { QJsonObject jsonObject = jsonArray.first().toObject(); QVector <double> x,y; for(int i=0;i< jsonObject.value("X").toArray().size();i++) { x.push_back(jsonObject.value("X").toArray()[i].toDouble()); y.push_back(jsonObject.value("Y").toArray()[i].toDouble()); }
-
@DemonLord
Your JSON code itself may be fine --- assuming the TCP server send you this JSON? However, the problem is passing it theQByteArray &data
--- how do you know when that is sufficiently filled to have the complete JSON document in it to parse successfully? Remember that TCP protocol sends messages in "chunks", anything from just 1 byte up to the full written bytes, at a time. That's what will arrive wherever you have your void QIODevice::readyRead() slot. It is your job to keep appending and buffering up bytes arriving until you have a full "message" to pass to yourparseData(QByteArray &data)
. -
so i need to include a readyread in my JSON? I dont understand what you mean sorry
-
@DemonLord said in On going data from TCP Server to a graph in the UI how do i do it?:
so i need to include a readyread in my JSON? I dont understand what you mean sorry
You don't.
The point here: ensure that you have received the full JSON document from your server before calling
parseData
.What was explained is that In the slot you connected to the
readyRead
signal, you should:- Read the data received
- Append that to a buffer
- Check if the buffer containers a full JSON document
- If not, do nothing special
- If the buffer contains the full JSON document -> remove the data from the buffer and send it for further parsing
-
@DemonLord
No.connect(chart,SIGNAL(tcpDataGUI(QByteArray&data)),this,SLOT(parseData(QByteArray))); // TcpDaraGUI was emitted after the data was converted from string to ascii,the parseData is a function on the UI
How does your
tcpDataGUI(QByteArray&data)
successfully gather all the data into theQByteArray&data
to pass, given that (as I understand it) the data arrives from a client over TCP?Separately, please do yourself a favor and change over to New Signal Slot Syntax for your
connect()
s, instead of thoseSIGNAL
/SLOT()
macros. I'm surprised your signature forSLOT(parseData(QByteArray))
even matches your declaredparseData(QByteArray &data)
....