Use repeater inside chartview
-
Hi, can anyone help me on the following?
In a qml file trying to dynamically create AreaSeries objects. Try to get this working but the only result is an empty window, without any significant application output or debugging error information what is going wrong. No chartobject or graphics are shown.
The data in the ListModel defined is a first step. Second step (after this concept appears to be working) will be removing the ListModel out of the qml, and placing it in the C++ environment. Code:
ChartView {
id: chartid
antialiasing: true//Valueaxis ValueAxis{ id:xAxis; min: 0; max: 40000; tickCount: 9 } ValueAxis{ id:yAxis; min: -200; max: 1400; tickCount: 17 } //Listmodel only for testing AreaSeries/Repeater concept ListModel{ id: listModel ListElement { x1: 18000; x2: 18200 ; y1: -100; y2: 400 } ListElement { x1: 25000; x2: 25200 ; y1: -100; y2: 1000 } ListElement { x1: 31000; x2: 31200 ; y1: -100; y2: 1200 } ListElement { x1: 39500; x2: 39700 ; y1: -100; y2: 1250 } } Repeater{ id: areaSeriesRepeater model: listModel delegate: Item{ AreaSeries { axisX: xAxis axisY: yAxis color: "grey" borderColor: "black" borderWidth: 2 upperSeries: LineSeries { XYPoint { x: model.x1 ; y: model.y2 } XYPoint { x: model.x2 ; y: model.y2 } } lowerSeries: LineSeries { XYPoint { x: model.x1 ; y: model.y1 } XYPoint { x: model.x2 ; y: model.y1 } } } } } }
-
Hereby a solution that works for me. Instead of using a repeater, this codesample works with the ChartView's onCompleted signal handler. In the onCompleted handler first three LineSeries are dynamically created, then an AreaSeries is created.
ChartView { id: chartid anchors.fill: parent antialiasing: true //Valueaxis ValueAxis{ id:xAxis; min: 0; max: 40000; tickCount: 9 } ValueAxis{ id:yAxis; min: -200; max: 1400; tickCount: 17 } //Listmodel only for testing Area- and LineSeries concept ListModel{ id: listModel ListElement { x1: 18000; y1: -100; x2: 18000 ; y2: 400 } ListElement { x1: 25000; y1: -100; x2: 25000 ; y2: 1000 } ListElement { x1: 31000; y1: -100; x2: 31000 ; y2: 1200 } ListElement { x1: 36500; y1: -100; x2: 39700 ; y2: 1250 } } Component.onCompleted: { var count = listModel.count; for(var i = 0;i < count;i ++) { if (i < count - 1) // add LineSeries { var lineTypeSeries = chartid.createSeries(ChartView.SeriesTypeLine, "line" + i, xAxis, yAxis); lineTypeSeries.color = "black"; lineTypeSeries.width = 2; lineTypeSeries.borderWidth = 0; lineTypeSeries.append(listModel.get(i).x1, listModel.get(i).y1); lineTypeSeries.append(listModel.get(i).x2, listModel.get(i).y2); } else { var areaTypeSeries = chartid.createSeries(ChartView.SeriesTypeArea, "area" + i, xAxis, yAxis); areaTypeSeries.pointsVisible = true; areaTypeSeries.color = "lightgrey"; areaTypeSeries.borderColor = "black"; areaTypeSeries.borderWidth = 2; areaTypeSeries.lowerSeries = chartid.createSeries(ChartView.SeriesTypeLine, "lowerSerie"); areaTypeSeries.lowerSeries.width = 0; areaTypeSeries.lowerSeries.borderWidth = 0; areaTypeSeries.lowerSeries.color = areaTypeSeries.borderColor; areaTypeSeries.lowerSeries.capStyle = 0x00; areaTypeSeries.lowerSeries.append(listModel.get(i).x1, listModel.get(i).y1); areaTypeSeries.lowerSeries.append(listModel.get(i).x2, listModel.get(i).y1); areaTypeSeries.upperSeries.append(listModel.get(i).x1, listModel.get(i).y2); areaTypeSeries.upperSeries.append(listModel.get(i).x2, listModel.get(i).y2); } } } }
-
If you don't place it inside an item object you get run time error: popup messagebox reporting a "Read access violation" and the application output windows says "QML Component: Delegate must be of Item type".
When using the Item object, no errors are reported, looks good, but application window (chartview) stays completely empty.
-
I think you will have to find another way to do this.
I tried this:
ChartView { id: chartid antialiasing: true width: parent.width height: 500 //Valueaxis ValueAxis{ id:xAxis; min: 0; max: 40000; tickCount: 9 } ValueAxis{ id:yAxis; min: -200; max: 1400; tickCount: 17 } //Listmodel only for testing AreaSeries/Repeater concept ListModel{ id: listModel ListElement { x1: 18000; x2: 18200 ; y1: -100; y2: 400 } ListElement { x1: 25000; x2: 25200 ; y1: -100; y2: 1000 } ListElement { x1: 31000; x2: 31200 ; y1: -100; y2: 1200 } ListElement { x1: 39500; x2: 39700 ; y1: -100; y2: 1250 } } Repeater{ id: areaSeriesRepeater model: listModel delegate: Item{ AreaSeries { id: areaseries axisX: xAxis axisY: yAxis color: "grey" borderColor: "black" borderWidth: 2 upperSeries: LineSeries { XYPoint { x: model.x1 ; y: model.y2 } XYPoint { x: model.x2 ; y: model.y2 } } lowerSeries: LineSeries { XYPoint { x: model.x1 ; y: model.y1 } XYPoint { x: model.x2 ; y: model.y1 } } Component.onCompleted: { chartid.children.push(areaseries) } } } } }
But this causes a segfault. I think the problem is that AreaSeries is not a direct child of ChartView.
-
Thnx for your idea's. I'm also working on a solution via the onCompleted signal handler. First result looks promising. I'll work it out some further, and when usefull I'll post it here. In the meantime if anyone has any idea's how handle this in a proper way, please share it.
-
Hereby a solution that works for me. Instead of using a repeater, this codesample works with the ChartView's onCompleted signal handler. In the onCompleted handler first three LineSeries are dynamically created, then an AreaSeries is created.
ChartView { id: chartid anchors.fill: parent antialiasing: true //Valueaxis ValueAxis{ id:xAxis; min: 0; max: 40000; tickCount: 9 } ValueAxis{ id:yAxis; min: -200; max: 1400; tickCount: 17 } //Listmodel only for testing Area- and LineSeries concept ListModel{ id: listModel ListElement { x1: 18000; y1: -100; x2: 18000 ; y2: 400 } ListElement { x1: 25000; y1: -100; x2: 25000 ; y2: 1000 } ListElement { x1: 31000; y1: -100; x2: 31000 ; y2: 1200 } ListElement { x1: 36500; y1: -100; x2: 39700 ; y2: 1250 } } Component.onCompleted: { var count = listModel.count; for(var i = 0;i < count;i ++) { if (i < count - 1) // add LineSeries { var lineTypeSeries = chartid.createSeries(ChartView.SeriesTypeLine, "line" + i, xAxis, yAxis); lineTypeSeries.color = "black"; lineTypeSeries.width = 2; lineTypeSeries.borderWidth = 0; lineTypeSeries.append(listModel.get(i).x1, listModel.get(i).y1); lineTypeSeries.append(listModel.get(i).x2, listModel.get(i).y2); } else { var areaTypeSeries = chartid.createSeries(ChartView.SeriesTypeArea, "area" + i, xAxis, yAxis); areaTypeSeries.pointsVisible = true; areaTypeSeries.color = "lightgrey"; areaTypeSeries.borderColor = "black"; areaTypeSeries.borderWidth = 2; areaTypeSeries.lowerSeries = chartid.createSeries(ChartView.SeriesTypeLine, "lowerSerie"); areaTypeSeries.lowerSeries.width = 0; areaTypeSeries.lowerSeries.borderWidth = 0; areaTypeSeries.lowerSeries.color = areaTypeSeries.borderColor; areaTypeSeries.lowerSeries.capStyle = 0x00; areaTypeSeries.lowerSeries.append(listModel.get(i).x1, listModel.get(i).y1); areaTypeSeries.lowerSeries.append(listModel.get(i).x2, listModel.get(i).y1); areaTypeSeries.upperSeries.append(listModel.get(i).x1, listModel.get(i).y2); areaTypeSeries.upperSeries.append(listModel.get(i).x2, listModel.get(i).y2); } } } }