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

QML ChartView lineseries with "blank" points



  • Hi all,

    I recently started working with qml and in particular with ChartView. I'm developing an app where I need to show a ChartView object with some LineSeries inside. I said "some LineSeries" but the end result should looks like a single line, the problem is that this single line has to be composed by different colours. It is certainly easier to understand with an image:
    Cattura.PNG

    So, here I have two lines, but I would like them to look like one. To do this, I would like to know if there is a way to tell the QXYSeries Object to insert something like a blank point, so that I don't have the straight lines, because they're something that des not represent the line I want to draw. The correct line should look like the following one, but with two different color:
    Catturad.PNG

    This is my current code:
    MyChartView.qml

    import QtQuick 2.15
    import QtQuick.Controls 2.15
    import QtCharts 2.15
    
    ChartView {
        id: chartId
    
        plotArea: Qt.rect(5, 5, chartId.width - 5, chartId.height - 5)
        margins { top: 10; bottom: 10; left: 10; right: 10; }
    
        plotAreaColor: "#000020"
        backgroundColor: "white"
        legend.visible: false
        antialiasing: true
    
        ValueAxis {
            id: yaxis
            min: 0
            max: 100
    
            labelsVisible: false
            gridVisible: false
            minorGridVisible: false
            visible: false
        }
    
        ValueAxis {
            id: xaxis
            min: 0
            max: 100
    
            labelsVisible: false
            gridVisible: false
            minorGridVisible: false
            visible: false
        }
    
        LineSeries {
            id: firstId
            axisX: xaxis
            axisY: yaxis
            useOpenGL: true
            name: "firstId"
            color: "red"
        }
    
        LineSeries {
            id: secondId
            axisX: xaxis
            axisY: yaxis
            useOpenGL: true
    
            name: "secondId"
            color: "white"
        }
    }
    

    cpp

    #include "chart.h"
    
    Chart::Chart(QObject *parent) : BaseChart(parent)
    {
    
    }
    
    void Chart::createDataPoint()
    {
    //this function popolates the firstId and secondId QVector<PointF>
        emit updateData();
    }
    
    void Chart::update(QAbstractSeries *series)
    {
        if (series) {
            QXYSeries *xySeries = static_cast<QXYSeries *>(series);
    
            if (xySeries->name() == "firstId")
                xySeries->replace(firstId);
            else
                xySeries->replace(secondId);
        }
    }
    

    .h

    #include <QObject>
    #include <QtCharts/QXYSeries>
    #include <QtCharts>
    #include <QtCharts/QAbstractSeries>
    #include "basechart.h"
    
    
    class Chart: public BaseChart
    {
        Q_OBJECT
    public:
        explicit Chart(QObject *parent = nullptr);
    
        Q_INVOKABLE void update(QAbstractSeries *series);
    
        void createDataPoint();
    
    signals:
        void updateData();
        void lineChanged();
    
    private:
        QVector<QPointF> firstId;
        QVector<QPointF> secondId;
    
    
    };
    
    

    baseChart.cpp

    #include <QObject>
    #include <QtCharts>
    
    QT_CHARTS_USE_NAMESPACE
    Q_DECLARE_METATYPE(QAbstractSeries *)
    Q_DECLARE_METATYPE(QAbstractAxis *)
    
    namespace charts {
    class BaseChart : public QObject
    {
        Q_OBJECT
    public:
        explicit BaseChart(QObject *parent = nullptr);
    
    
    signals:
    
    protected:
        
    
    };
    }
    

    basechart.h

    BaseChart::BaseChart(QObject *parent) : QObject(parent)
    {
        qRegisterMetaType<QAbstractSeries*>();
        qRegisterMetaType<QAbstractAxis*>();
    }
    
    

    and from this qml I call the update on the series objects

    import QtQuick 2.15
    import QtQuick.Controls 2.15
    import QtQuick.Layouts 1.15
    
    Item {
        id: container
        anchors.fill: parent
    
        Connections {
            target: chart
            function onUpdateData() {
                console.log("We need to update data")
                chart.update(chartId.series(0))
                chart.update(chartId.series(1))
            }
        }
    
    MyChartView {
                id: chartId
            }
    }
    

    I'm using Qt 5.15.2 on Windows 10 64bit with MinGw64.
    If something is not clear please ask me! I had to delete some part of my code due to privacy policies but I hope it's clear what I would like to do.

    The only solution I can think of right now is to create n-LineSeries object and assign to them the points and the color to display, but I would like to find an easier solution because this means that for my specific purpose I can reach more than 40-50 LineSeries to display on the chart. I would also need to create the LineSeries objects dinamycally from c++, but that should not be a problem.

    Anyway, I know that in some charts libraries there is the possiblity to add something like a NoValue to avoid this behaviour, or there are some tricks, maybe also in Qt is there something similar?

    Thanks in advance!



  • The solution I adopted in the end is to create dinamically a single LineSeries object for every line color, and that works pretty well even if I have to create 40-50 lineSeries objects.
    I'm not pretty sure that the way I'm adding LineSeries is the best (I don't like the approach I used, but at the moment I don't see other possibilities).
    When I need to draw the lines what I do is:

    1. send a signal from c++ to qml that we need to draw new lines, with the number of lines to be drawn.
    2. with a Connections object I intercept the signal in qml and inside a for I create a new LineSeries element using chartView.CreateSeries(). Then I pass the series back to c++, with the number of the LineSeries created, so that I know which points I have to assign the that LineSeries object.

    I know that is not a clean approach, if somebody has any hints please tell me.



  • The solution I adopted in the end is to create dinamically a single LineSeries object for every line color, and that works pretty well even if I have to create 40-50 lineSeries objects.
    I'm not pretty sure that the way I'm adding LineSeries is the best (I don't like the approach I used, but at the moment I don't see other possibilities).
    When I need to draw the lines what I do is:

    1. send a signal from c++ to qml that we need to draw new lines, with the number of lines to be drawn.
    2. with a Connections object I intercept the signal in qml and inside a for I create a new LineSeries element using chartView.CreateSeries(). Then I pass the series back to c++, with the number of the LineSeries created, so that I know which points I have to assign the that LineSeries object.

    I know that is not a clean approach, if somebody has any hints please tell me.


Log in to reply