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

ChartView wrapper



  • Hi all. I have wrapper for ChartView that looks like:

    ChartWrapper.qml:

    import QtQuick 2.9
    import QtCharts 2.2
    
    Item {
        property alias xAxisLabel: xAxisLabel.text
        property alias yAxisLabel: yAxisLabel.text
    
        Text {
            id: yAxisLabel
            y: parent.height - height
            text: "yAxis"
            color: "white"
            font {
                family: fontProvider.font
                pixelSize: 9
            }
            transform: Rotation {
                angle: -90
            }
            smooth: false
            antialiasing: false
        }
    
        Rectangle {
            id: clipRectangle
            anchors.top: parent.top
            anchors.bottom: parent.bottom
            anchors.left: yAxisLabel.right
            anchors.leftMargin: -5
            anchors.right: xAxisLabel.left
            color: "red"
    
            clip: true
    
            ChartView {
                id: chart
                x: -34
                y: -17
                width: parent.width + 50
                height: parent.height + 45
    
                legend.visible: false
                backgroundColor: "black"
    
                ValueAxis {
                    id: xAxis
                    gridVisible: false
                    minorGridVisible: false
                    labelsVisible: false
                    labelFormat: ""
                    tickCount: 2
                    minorTickCount: 0
                    color: "white"
                }
    
                ValueAxis {
                    id: yAxis
                    gridVisible: false
                    minorGridVisible: false
                    labelsVisible: false
                    labelFormat: ""
                    tickCount: 2
                    minorTickCount: 0
                    color: "white"
                }
    
    //            LineSeries {
    //                axisX: xAxis
    //                axisY: yAxis
    //                color: "white"
    
    //                XYPoint { x: 0; y: 0 }
    //                XYPoint { x: 1.1; y: 2.1 }
    //                XYPoint { x: 1.9; y: 3.3 }
    //                XYPoint { x: 2.1; y: 2.1 }
    //                XYPoint { x: 2.9; y: 4.9 }
    //                XYPoint { x: 3.4; y: 3.0 }
    //                XYPoint { x: 4.1; y: 3.3 }
    //            }
            }
        }
    
        Text {
            id: xAxisLabel
            anchors.right: parent.right
            anchors.bottom: parent.bottom
            text: "xAxis"
            color: "white"
            font {
                family: fontProvider.font
                pixelSize: 9
            }
            smooth: false
            antialiasing: false
        }
    }
    

    and further i want to write something like:
    main.qml:

    Window {
      ChartWrapper {
        xAxisLabel: "x"
        yAxisLabel: "y"
        LineSeries {
          color: "white"
    
          XYPoint { x: 0; y: 0 }
          XYPoint { x: 1.1; y: 2.1 }
          XYPoint { x: 1.9; y: 3.3 }
          XYPoint { x: 2.1; y: 2.1 }
          XYPoint { x: 2.9; y: 4.9 }
          XYPoint { x: 3.4; y: 3.0 }
          XYPoint { x: 4.1; y: 3.3 }
        }
      }
    }
    

    How can i achieve this?



  • @egor-utsov I understand the problem. If you want to do that, you must ensure that the ChartView component is the main component in your ChartWrapper.qml. I don't know if you are going to evaluate this kind of solution.

    The other solution is about the data. I can see in this line:

    XYPoint { x: 0; y: 0 }
          XYPoint { x: 1.1; y: 2.1 }
          XYPoint { x: 1.9; y: 3.3 }
          XYPoint { x: 2.1; y: 2.1 }
          XYPoint { x: 2.9; y: 4.9 }
          XYPoint { x: 3.4; y: 3.0 }
          XYPoint { x: 4.1; y: 3.3 }
    

    that you are injecting data into your component with LineSeries component. Is it necessary for this structure? You can establish a new variant property in your ChartWrapper component and inject the data with this property. Or you can explore to apply the model-view-delegate paradigm to your solution. It's up to you. Good luck!



  • @egor.utsov said in ChartView wrapper:

    How can i achieve this?

    You can't. You must add/remove your series dynamically in that case.
    The Qt graph examples are a bit useless because they mainly show statically defined series, as in your example. It is highly unlikely that anyone would ever write a Qt program to only show static data like that.

    In the end, you really need to generate and add the series dynamically, so you may as well start thinking dynamically from now on.



  • Hi @oria66, could you provide some examples for how to make ChartView main component of ChartWrapper and how to apply model-view-delegate here?

    Hi @Diracsbracket . Yes, i tried to add series dynamically, but here another problem arise. After the series was changed, ChartView do not autoscale its area, like with statically added series. Is it possible to achieve same behaviour in dynamically case?



  • @egor.utsov said in ChartView wrapper:

    ChartView do not autoscale its area, like with statically added series. Is it possible to achieve same behaviour in dynamically case

    You may have to set the min and max properties of the axisX yourself (not sure whether it is required for the axisY too) at the time you add the series.



  • @Diracsbracket Thank you for the answers. I will try it.



  • I ended up with the following solution

    ClippedChart.qml:

    Item {
        property alias xAxisLabel: xAxisLabel.text
        property alias yAxisLabel: yAxisLabel.text
        property var points // Add this property
        ...
    
        onPointsChanged: {
            chart.removeAllSeries();
            var s = chart.createSeries(ChartView.SeriesTypeLine, "default", xAxis, yAxis);
            s.color = "white";
            s.width = 1;
    
            var rightMost;
            var topMost;
    
            for (var i = 0; i < points.length; ++i) {
                var point = points[i];
                s.append(points[i].x, points[i].y);
    
                if (!rightMost) {
                    rightMost = point;
                } else {
                    if (rightMost.x < point.x)
                        rightMost = point;
                }
    
                if (!topMost) {
                    topMost = point;
                } else {
                    if (topMost.y < point.y)
                        topMost = point;
                }
            }
    
            chart.axisX(s).min = 0.0;
            chart.axisX(s).max = rightMost.x;
            chart.axisY(s).min = 0.0;
            chart.axisY(s).max = topMost.y;
        }
    }
    

    and then create instance of it like this

    ClippedChart {
                    id: fanSpeedGraph
                    anchors.top: fanSwitch.bottom
                    anchors.bottom: monitoringPane.bottom
                    anchors.left: monitoringPane.left
                    anchors.leftMargin: 2
                    anchors.right: monitoringPane.right
                    anchors.rightMargin: 2
                    yAxisLabel: "speed"
                    xAxisLabel: "t"
    
                    points: [
                        Qt.point(0, 0),
                        Qt.point(1.1, 2.1),
                        Qt.point(1.9, 3.3),
                        Qt.point(2.1, 2.1),
                        Qt.point(2.9, 4.9),
                        Qt.point(3.4, 3.0),
                        Qt.point(4.1, 3.3)
                    ]
                }
    

Log in to reply