Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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  ");

  • Lifetime Qt Champion

    @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.


  • Lifetime Qt Champion

    @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


  • Lifetime Qt Champion

    @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 the QByteArray &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 your parseData(QByteArray &data).



  • so i need to include a readyread in my JSON? I dont understand what you mean sorry


  • Lifetime Qt Champion

    @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:

    1. Read the data received
    2. Append that to a buffer
    3. Check if the buffer containers a full JSON document
    4. If not, do nothing special
    5. 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 the QByteArray&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 those SIGNAL/SLOT() macros. I'm surprised your signature for SLOT(parseData(QByteArray)) even matches your declared parseData(QByteArray &data)....


Log in to reply