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

QChart + background image



  • I'm using QChart and QChartView to produce my 2D line graphs.

    Now, I would like to create a 2D line chart that will contain a background image, like this example below:
    image.png

    How can I do it using Qt? Is this possible?



  • @mrjj thank you a lot!

    The original source-code of this old post was not working and it have a lot of warnings...
    So I modified to get a complete and zero errors/warnings modern Qt example.
    Here is the full source-code:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <QtCharts/QChartView>
    #include <QtCharts/QLineSeries>
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        //Build a series to add to the chart
        QtCharts::QLineSeries *series = new QtCharts::QLineSeries();
        *series << QPointF(11, 1) << QPointF(13, 3) << QPointF(17, 6) << QPointF(18, 3) << QPointF(20, 2);
    
        //Create a chart object and format
        QtCharts::QChart *chart = new QtCharts::QChart();
        chart->legend()->hide();
        chart->addSeries(series);
        chart->createDefaultAxes();
    
        chart->axes(Qt::Vertical).first()->setGridLineVisible(false);
        chart->axes(Qt::Horizontal).first()->setGridLineVisible(false);
    
        //Bring in the background image from Qt resource
        QImage skyplot(":/SkyPlot.jpg");
        if (skyplot.isNull()) { return; }
    
        // ===== CHART VIEWER ===== //
        // Create a Chart Viewer:
        QtCharts::QChartView* chartView = new QtCharts::QChartView();
        //Add the chart to the view widget
        chartView->setChart(chart);
        chartView->setRenderHint(QPainter::Antialiasing, true);
    
        //Note: Since we added the chart to the view we can now
        //scale and translate the image appropriately. The chart
        //has an appropriate size.
    
        //Grab the size of the plot and view areas
        int width = static_cast<int>(chart->plotArea().width());
        int height = static_cast<int>(chart->plotArea().height());
        int ViewW = static_cast<int>(chartView->width());
        int ViewH = static_cast<int>(chartView->height());
    
        //scale the image to fit plot area
        skyplot = skyplot.scaled(QSize(width, height));
    
        //We have to translate the image because setPlotAreaBackGround
        //starts the image in the top left corner of the view not the
        //plot area. So, to offset we will make a new image the size of
        //view and offset our image within that image with white
        QImage translated(ViewW, ViewH, QImage::Format_ARGB32);
        translated.fill(Qt::white);
        QPainter painter(&translated);
        QPointF TopLeft = chart->plotArea().topLeft();
        painter.drawImage(TopLeft, skyplot);
    
        //Display image in background
        chart->setPlotAreaBackgroundBrush(translated);
        chart->setPlotAreaBackgroundVisible(true);
    
        // Add widget to GUI:
        ui->gridLayout->addWidget(chartView);
    }
    

    3 key points:

    • In the UI file, you have to add a gridLayout to the MainWindow window.
    • Add the charts in your *.pro file Qt += charts
    • The background image must be in a Qt resource file

    The final result is this chart + a backgroud image:
    16d3190a-46ad-4037-993f-788da6eb1a97-image.png



  • I saw this Qt3DSurface that enable to put a texture in the plot area (link here).
    I don't know if it can be used in this case.

    69951d11-f305-4c81-872c-c62b2b52db37-image.png

    Anyone can confirm it?
    I don't know is is possible to generate a Qt3DSurface, rotate it to get a 2D plan (X and Y axis only) and:

    • Plot a time series (like a QChart)
    • Add a background "texture" with the desired image (like the first post above).

    Is this possible?


  • Lifetime Qt Champion

    Hi
    Have a look here
    https://forum.qt.io/topic/82640/center-background-image-in-qchart
    (last post)
    They used a brush to get a background picture. and transformed it to only be in the plot area.
    Disclaimer. I have not tried it :)



  • @mrjj thank you a lot!

    The original source-code of this old post was not working and it have a lot of warnings...
    So I modified to get a complete and zero errors/warnings modern Qt example.
    Here is the full source-code:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <QtCharts/QChartView>
    #include <QtCharts/QLineSeries>
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        //Build a series to add to the chart
        QtCharts::QLineSeries *series = new QtCharts::QLineSeries();
        *series << QPointF(11, 1) << QPointF(13, 3) << QPointF(17, 6) << QPointF(18, 3) << QPointF(20, 2);
    
        //Create a chart object and format
        QtCharts::QChart *chart = new QtCharts::QChart();
        chart->legend()->hide();
        chart->addSeries(series);
        chart->createDefaultAxes();
    
        chart->axes(Qt::Vertical).first()->setGridLineVisible(false);
        chart->axes(Qt::Horizontal).first()->setGridLineVisible(false);
    
        //Bring in the background image from Qt resource
        QImage skyplot(":/SkyPlot.jpg");
        if (skyplot.isNull()) { return; }
    
        // ===== CHART VIEWER ===== //
        // Create a Chart Viewer:
        QtCharts::QChartView* chartView = new QtCharts::QChartView();
        //Add the chart to the view widget
        chartView->setChart(chart);
        chartView->setRenderHint(QPainter::Antialiasing, true);
    
        //Note: Since we added the chart to the view we can now
        //scale and translate the image appropriately. The chart
        //has an appropriate size.
    
        //Grab the size of the plot and view areas
        int width = static_cast<int>(chart->plotArea().width());
        int height = static_cast<int>(chart->plotArea().height());
        int ViewW = static_cast<int>(chartView->width());
        int ViewH = static_cast<int>(chartView->height());
    
        //scale the image to fit plot area
        skyplot = skyplot.scaled(QSize(width, height));
    
        //We have to translate the image because setPlotAreaBackGround
        //starts the image in the top left corner of the view not the
        //plot area. So, to offset we will make a new image the size of
        //view and offset our image within that image with white
        QImage translated(ViewW, ViewH, QImage::Format_ARGB32);
        translated.fill(Qt::white);
        QPainter painter(&translated);
        QPointF TopLeft = chart->plotArea().topLeft();
        painter.drawImage(TopLeft, skyplot);
    
        //Display image in background
        chart->setPlotAreaBackgroundBrush(translated);
        chart->setPlotAreaBackgroundVisible(true);
    
        // Add widget to GUI:
        ui->gridLayout->addWidget(chartView);
    }
    

    3 key points:

    • In the UI file, you have to add a gridLayout to the MainWindow window.
    • Add the charts in your *.pro file Qt += charts
    • The background image must be in a Qt resource file

    The final result is this chart + a backgroud image:
    16d3190a-46ad-4037-993f-788da6eb1a97-image.png


Log in to reply