Solved 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:
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:
This is my current code:
MyChartView.qmlimport 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:- send a signal from c++ to qml that we need to draw new lines, with the number of lines to be drawn.
- 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:- send a signal from c++ to qml that we need to draw new lines, with the number of lines to be drawn.
- 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.