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

More flexible chart axis labels



  • I am currently using ValueAxis for the X axis of a charting application.

    The data is updated dynamically to plot the progress of some background activity as new data comes in. The X axis represents something like an iteration count so it should always be integer. Therefore, I have to do some work to set the tick count and the upper range of the axis so that the labels always come out as integers.

    In addition, I would like some more flexibility in what I am displaying for the labels. Rather than simply showing an integer value I would like to map it to something more meaningful for the application. This leads me to wonder about using CategoryAxis.

    I have not tried very hard so far but I did do an initial experiment where I replaced my current ValueAxis X axis with a hard coded CategoryAxis (so no attempts to do anything dynamic) and even that is not working for me. I am wondering whether it even makes sense to try to use a CategoryAxis as an X axis in this way - the example I have seen all use it for a Y axis.

    However, assuming I have just made a mistake in the above and there is not a fundamental problem, I am concerned that CategoryAxis does not seem to be very well suited to dynamic updates in the same way that ValueAxis is. Although it is possible to append to the labels, it will periodically be necessary to completely respecify the labels (for example, consider that when the iteration count is 10, I might want to show labels at intervals of 2, but when it is 100 I might want to show them at intervals of 20). The API would seem to require that I delete all labels and redefine them each time I wanted to adjust the axis.

    Before I spend a lot of time on this, I was wondering if anyone had an experience of trying to do anything like this and whether it is likely to work.



  • Well I did spend a little more time on this. I found why my basic attempt with hard coded CategoryRange did not work. I also needed to set min and max on the axis, which is interesting as these properties are currently undocumented, though they are referenced in the code of at least one of the Qt examples I looked at. Perhaps this will be useful information for someone at some point.

    Having resolved that, I also tried out some "pseudo-dynamic" behaviour, whereby I dynamically added labels as the X range of arriving data increased beyond the current axis range. This seemed to work well performance-wise, though obviously the labels become increasingly bunched up. Next step is to try what I really want to do which is to respecify the complete set of labels when the X range hits certain sizes.



  • For now, I am updating the axis labels when the number of labels reaches some threshold - in my case, 10. At this point, I prune every other label and double the step interval for appended labels. Thus I have between 5 and 9 labels at any one time. This appears to work reasonably well.

        CategoryAxis {
            id: axisX
            labelsPosition: CategoryAxis.AxisLabelsPositionOnValue
            
            startValue: 0
            min: 0
            max: 10
    
            property var stepInterval: 2
    
            // Hard code initial set of 5 labels
            CategoryRange {
                label: "2"
                endValue: 2
            }
            ...
            CategoryRange {
                label: "10"
                endValue: 10
            }
        }
    
        Connections {
            target: chartData
            onNpointChanged: {
                if (chartData.npoint > axisX.max) {
                    // Reached end of axis - extend by current step interval
                    axisX.max += axisX.stepInterval;
                    axisX.append(axisX.max.toString(), axisX.max);
                }
                if (axisX.count === 10) {
                    [ ... prune even indexed label using axisX.remove() ]
                    axisX.stepInterval *= 2;
                }
            }
        }
    
    
    

Log in to reply