Andy Shaw

Qt Support – Aligning chart views underneath each other

Published Friday June 14th, 2019
2 Comments on Qt Support – Aligning chart views underneath each other
Posted in Charts, Qt

One thing that comes up occasionally in support is that when you have multiple chart views that it would be good to align them up underneath each other so that the actual plotted size is the same for both charts. If you have similar sizes for the axes then this is easily achieved as they will take up the same width and it will align for you. However, if this is not the case as it so often is, then we can use the margins to force it to have the sizes that we want. So let’s say that our chart currently looks like:

Chart with unaligned axes

If you are using C++ for your chart code then this can be achieved with the aid of a single slot, that can be connected to the QChart::plotAreaChanged() signal. To start off we need to prevent recursion from happening as we will be changing margins and so on but we want to let the internals still do their thing so we don’t want to block signals. So to do that we will just have a static boolean which we will set to true to indicate that we are in the middle of our calculations:

    void updatePlotArea(const QRectF &area)
        static bool fixing = false;
        if (fixing)
        fixing = true;

The next thing we need to do is work out what chart is the best one to be used for aligning the others against, this means picking the one that has the largest left value for the plot area (i.e. the one that has the widest axis). We use the currently changed one as a starting point for this and if any are in fact better we change the margins for those as it will ensure we have the most size available for the plot area at any given point for the largest axis.

    QChart *bestChart = (QChart *)sender();
         QRectF bestRect = area;
         foreach(QChart *chart, charts) {
            if (chart->plotArea().left() > bestRect.left()) {
                bestChart = chart;
                bestRect = chart->plotArea();
                chart->setMargins(QMargins(20, 0, 20, 0));

Then, with the exception of the one that ends up being the best one we adjust the margins to ensure that it matches the best one so that they are aligned correctly by setting the margins to be the existing margin plus the difference between the best chart’s plot area and this chart’s plot area. Finally we send any posted events to ensure it is updated right away for us.

    foreach(QChart *chart, charts) {
        if (bestChart != chart) {
            const int left = chart->margins().left() +
                (bestRect.left() - chart->plotArea().left());
            const int right = chart->margins().right() +
                (chart->plotArea().right() - bestRect.right());
            chart->setMargins(QMargins(left, 0, right, 0));
    fixing = false;

This will give us the two charts aligned to look like:


As for doing this in QML, we can do something similar in a function which is called via onPlotAreaChanged.

    property bool fixing: false
    property var chartViews: [chartview, chartview_b]
    function updatePlotArea(chart, area) {
        if (fixing)
        fixing = true
        var tmpChart
        var bestRect = chart.plotArea
        var bestChart = chart
        for (var i = 0; i < chartViews.length; i++) {
           tmpChart = chartViews[i]
           if (tmpChart.plotArea.left >
               Math.ceil(bestRect.left) ||
               (Math.ceil(tmpChart.plotArea.left) === 
                Math.ceil(bestRect.left) &&
                Math.floor(tmpChart.plotArea.right) < 
                Math.floor(bestRect.right))) {
                    bestChart = tmpChart;
                    bestRect = tmpChart.plotArea;
        bestRect.left = Math.ceil(bestRect.left)
        bestRect.right = Math.floor(bestRect.right)
        for (i = 0; i < chartViews.length; i++) {
            tmpChart = chartViews[i]
            if (tmpChart !== bestChart) {
                var newLeft = 20 + bestRect.left -
                var newRight = 20 +
                      Math.ceil(tmpChart.plotArea.right) -
                tmpChart.margins.left = newLeft
                tmpChart.margins.right = newRight
        fixing = false;

The only difference being is that we account for the fact that the plot area is using real values and margins are still integer based so we do some extra accounting for that as a result.

In other news from the support desk, to reiterate the value of reporting bugs directly to the support team as a customer. As a customer indicated the issue reported in we were able to quickly find a solution and also get that integrated in time for the next release. It had been reported earlier this year, but was given a lower priority because Qt Quick Controls 1 is deprecated and therefore no one had scheduled time to investigate it. As always, when a bug is reported to us from a customer it will increase the priority and in cases like this we are able to solve it much quicker as a result as the support team can spend time on it too.

Do you like this? Share it
Share on LinkedInGoogle+Share on FacebookTweet about this on Twitter

Posted in Charts, Qt


Patrick Hisni Brataas says:

Looking at the QML code it looks like it has some syntax errors

Andy Shaw Andy Shaw says:

Thanks for pointing that out! Seems that it got lost when I copied the code from my editor and I completely missed it.

Commenting closed.

Get started today with Qt Download now