PDA

View Full Version : Charts in QtQuick: creating a line series with bar sets



Urthas
4th July 2016, 22:30
This question is admittedly a little odd, and convoluted.

Let me start by acknowledging that it does not actually make sense to use a scatter/line/spline chart when there is no inherent relationship between y and x (i.e., y cannot reasonably be construed to be a function of x).

The non-scientific reality is that many people simply want to see a trend line. Consider the case wherein a measurement is collected every day, and we are interested in charting monthly averages. The x axis is the month, and the y axis is the average value. Clearly, this is best modelled with a BarSet because of the nature of the data (and this becomes clear when we consider that we prefer "Sept" over 9 on the x axis). But the Powers That Be are insisting on a trend line. The problem is that a LineSeries is composed of one or more instances of XYSeries, and XYSeries consists of two real numbers (x and y).

Can this be done using the QtChart module? If so, how might I go about it? Any insights are appreciated.

(I'll update (and hopefully answer!) this question as I go along, but figured I'd get things rolling on this front.)

Update:

Before:



BarSeries {
id: barSeries

axisX: BarCategoryAxis { categories: dummyData.months }

BarSet {
id: appetiteBars

label: "Appetite"
values: dummyData.appetite
}
}


After:



LineSeries {
id: lineSeries

axisX: BarCategoryAxis { categories: dummyData.months }

XYPoint { x: 0; y: dummyData.appetite[0] }
XYPoint { x: 1; y: dummyData.appetite[1] }
XYPoint { x: 2; y: dummyData.appetite[2] }
XYPoint { x: 3; y: dummyData.appetite[3] }
XYPoint { x: 4; y: dummyData.appetite[4] }
XYPoint { x: 5; y: dummyData.appetite[5] }
}


My brain still rebels against doing this, and it's much more cumbersome to implement as a line series (i.e., per value, rather than dumping the whole array into a BarSet) but it works...

anda_skoa
5th July 2016, 09:18
You could try if you could use an Instantiator element to create the XYPoint instances.

Alternatively that looks like something that could easily be done with a custom item.

Cheers,
_

Urthas
5th July 2016, 17:24
The "solution" I came up with above works until I add another line series to the chart. Then I get duplicate x axes. So I will take a look at Instantiator, thanks.

Urthas
5th July 2016, 22:01
Updated solution, to take care of multiple x-axes:


LineSeries {
id: appetiteSeries

axisX: BarCategoryAxis { categories: dummyData.months }
name: qsTr("Appetite")

XYPoint { x: 0; y: dummyData.appetite[0] }
XYPoint { x: 1; y: dummyData.appetite[1] }
XYPoint { x: 2; y: dummyData.appetite[2] }
XYPoint { x: 3; y: dummyData.appetite[3] }
XYPoint { x: 4; y: dummyData.appetite[4] }
XYPoint { x: 5; y: dummyData.appetite[5] }
}

LineSeries {
id: energySeries

axisX: BarCategoryAxis { visible: false }
name: qsTr("Energy")

XYPoint { x: 0; y: dummyData.energy[0] }
XYPoint { x: 1; y: dummyData.energy[1] }
XYPoint { x: 2; y: dummyData.energy[2] }
XYPoint { x: 3; y: dummyData.energy[3] }
XYPoint { x: 4; y: dummyData.energy[4] }
XYPoint { x: 5; y: dummyData.energy[5] }
}

The key point here is to make the x-axis of subsequent series invisible.

However, this only works as-is with hard-coded data. Putting the correct number of series with the correct names and XYPoint values, dynamically (as in the case of fetching from a data layer), is a whole other kettle of fish. Perhaps Instantiator will be helpful there, i.e., using a LineSeries as a delegate. We'll see.

anda_skoa
5th July 2016, 22:36
LineSeries is an Item I think, so it should even work with a Repeater.
I was thinking of using Instantiator to create XYPoint instances.

Not sure though if that is supported by LineSeries.

Cheers,
_