Search code examples
chartsqmllabelhovertooltip

QML PolarChart point label on hover


There is that QML PolarChart example. (https://doc.qt.io/qt-6/images/examples_qmlpolarchart1.png)

As you see, those points are nameless. What I want is to see what exact point's values are by hovering over or clicking it. There is an option to show labels for all points, but since in my project there are too much of them, I need to show only one particular point label. Or tooltip over it.

Are there any built-in options to do it for series or points? Maybe there is a way to determine point by hovering over it using "onHovered" signal for series component? Qt5.15 is available for me. No Qt6.


Solution

  • This is how you would solve your question (basically your solution). I just want to confirm that it is not a workaround, what makes you feel this way? You use the functionality that is provided by the ChartView types to solve your task.

    By using the hovered(point point, bool state) signal you can handle when a point is hovered (state = true) and loses hover again (state = false). Using the mapToPosition function given by the ChartView you can convert the data point into a position to assign that to the ToolTip.

    import QtQuick 2.15
    import QtQuick.Controls 2.15
    import QtCharts 2.15
    
    ChartView {
        id: chart
        width: 640
        height: 480
        antialiasing: true
    
        ToolTip {
            id: toolTip
            visible: false
        }
    
        ScatterSeries {
            id: scatter
            name: "Scatter"
            axisX: ValueAxis { min: 1; max: 3 }
            axisY: ValueAxis { min: 1; max: 2.5 }
    
            XYPoint { x: 1.5; y: 1.5 }
            XYPoint { x: 1.5; y: 1.6 }
            XYPoint { x: 1.57; y: 1.55 }
            XYPoint { x: 1.8; y: 1.8 }
            XYPoint { x: 1.9; y: 1.6 }
            XYPoint { x: 2.1; y: 1.3 }
            XYPoint { x: 2.5; y: 2.1 }
    
            onHovered: function(point, state) {
                toolTip.text = point.x + ", " + point.y
                toolTip.visible = state
                let p = chart.mapToPosition(point, scatter)
                toolTip.x = p.x
                toolTip.y = p.y - toolTip.height
            }
        }
    }
    

    enter image description here


    UPDATE

    To get the ToolTips for the upper series of an AreaSeries only you would need to listen to the signal of this exact LineSeries as shown below. Unfortunately the point that is given as the parameter of the LineSeries hovered signal depends on where you put the mouse cursor at and isn't restricted to the provided points only as with a ScatterSeries. So you usually get interpolated points with a lot of decimal places. You could work around that by drawing a ScatterSeries on top of the AreaSeries and use the hovered signal from that series instead. If you want that though you could round the values for smaller tool tips.

    PolarChartView {
        id: chart
        title: "Some Polar Area Series"
        width: 640
        height: 480
        legend.visible: false
        antialiasing: true
    
        ToolTip {
            id: toolTip
            visible: false
        }
    
        ValueAxis { id: axis1 }
        ValueAxis { id: axis2 }
    
        LineSeries {
            id: lowerLine
            axisAngular: axis1
            axisRadial: axis2
    
            // Please note that month in JavaScript months are zero based, so 2 means March
            XYPoint { x: 0;  y: 15 }
            XYPoint { x: 2;  y: 35 }
            XYPoint { x: 3;  y: 50 }
            XYPoint { x: 5;  y: 75 }
            XYPoint { x: 6;  y: 102 }
            XYPoint { x: 9;  y: 132 }
            XYPoint { x: 10;  y: 100 }
            XYPoint { x: 12;  y: 120 }
            XYPoint { x: 16;  y: 140 }
            XYPoint { x: 20;  y: 150 }
        }
        LineSeries {
            id: upperLine
            axisAngular: axis1
            axisRadial: axis2
    
            // Please note that month in JavaScript months are zero based, so 2 means March
            XYPoint { x: 0; y: 30 }
            XYPoint { x: 2; y: 55 }
            XYPoint { x: 3; y: 80 }
            XYPoint { x: 5; y: 105 }
            XYPoint { x: 6; y: 125 }
            XYPoint { x: 9; y: 160 }
            XYPoint { x: 10; y: 140 }
            XYPoint { x: 12; y: 140 }
            XYPoint { x: 16; y: 170 }
            XYPoint { x: 20; y: 200 }
    
            onHovered: function(point, state) {
                toolTip.text = point.x + ", " + point.y
                toolTip.visible = state
                let p = chart.mapToPosition(point, upperLine)
                toolTip.x = p.x
                toolTip.y = p.y - toolTip.height
            }
        }
    
        AreaSeries {
            axisAngular: axis1
            axisRadial: axis2
            lowerSeries: lowerLine
            upperSeries: upperLine
        }
    }
    

    enter image description here