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

Qchart background image tiled instead of stretched



  • Hello everyone, back again with another head-scratcher. Hopefully I don't send you on a wild goose chase like yesterday.

    So I'm putting a background image on a QChart - my code is based on the code found here: https://forum.qt.io/topic/108046/qchart-background-image
    Which is excellent, and has gotten me pretty far, but I'm running into an issue of my image tiling itself instead of stretching the width of the chart. The portion of my code I think is relevant is below, and I'll discuss what I've tried below that.

        //Spline Graph
        initialSplineSeries = new QSplineSeries();
        initialSplineSeries->setName("initial spline series");
        for(int i = 0; i < 134; ++i)
        {
            initialSplineSeries->append(wavelength_arr[i], 0);
        }
        splineChart = new QChart();
        splineChart->legend()->hide();
        splineChart->addSeries(initialSplineSeries);
        splineChart->setTitle("Current Wavelength Mix");
        axisX = new QValueAxis;
        axisY = new QValueAxis;
        axisX->setRange(350, 750);
        axisY->setRange(0, 100);
        splineChartView = new QChartView();
        splineChartView->setChart(splineChart);
        splineChartView->setRenderHint(QPainter::Antialiasing, true);
        splineChartView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        splineChart->setAxisX(axisX);
        splineChart->setAxisY(axisY);
        initialSplineSeries->attachAxis(axisX);
        initialSplineSeries->attachAxis(axisY);
        splineChart->axes(Qt::Vertical).first()->setGridLineVisible(false);
        splineChart->axes(Qt::Horizontal).first()->setGridLineVisible(false);
        //-----setting up a background image for the graph----
        QImage spectrumFill(":/images/spectrumfill.jpg");
        
        //get the graph width and height and scale the image to it
        int chart_width = static_cast<int>(splineChart->plotArea().width());
        int chart_height = static_cast<int>(splineChart->plotArea().height());
        int view_width = static_cast<int>(splineChartView->width());
        int view_height = static_cast<int>(splineChartView->height());
        spectrumFill = spectrumFill.scaled(QSize(chart_width, chart_height));
        qDebug() << "chart width: " << chart_width;
        qDebug() << "chart height: " << chart_height;
        qDebug() << "view width: " << view_width;
        qDebug() << "view height: " << view_height;
    
        //this will translate the image, otherwise it puts it in the top left -
        //so it has to be translated to where the chart actually is
        QImage translated_spectrumFill(view_width, view_height, QImage::Format_ARGB32);
        translated_spectrumFill.fill(Qt::white);
        QPainter painter(&translated_spectrumFill);
        QPointF TopLeft = splineChart->plotArea().topLeft();
        painter.drawImage(TopLeft, spectrumFill);
        splineChart->setPlotAreaBackgroundBrush(translated_spectrumFill);
        splineChart->setPlotAreaBackgroundVisible(true);
        //lots of other stuff happens
        dimmerLayout->addWidget(splineChartView, 0, 0, 4, -1);
    

    So the things I've tried are hard-coding the values for chart_width/height and view_width/height. chart_width/height just stretches the image within it's tiled box, and cuts part of it off, and view_width/height stretches the width of the white border between the images, which both make sense given the tiled setup.
    I've also tried all the aspect ratios inside of spectrumFill.scaled(QSize(x, y), Qt::AspectRatio);
    Each one seems to do what it says it will, but only within the confines of the tiled box size, and doesn't seem to change the tiled box size itself.
    I believe the translation is working close to correctly - it does look like a little bit of it is cut off at the far left and right sides. This may be solved once the stretching is working properly.

    Ok I think that's everything - how do I make the image stretch??



  • Shoot I just realized I meant to put an image on this as well:
    tiled_graph.png



  • Alright everyone, since I have so many interested parties looking and asking questions ;)
    I found a solution that I hate but works for me. I'll probably have to revisit it in the future but it does what I need for an upcoming demo.

    So the problem is somehow still with the code that is meant to draw a nice white border around the image. I believe that what the previous solution was trying to do was to keep the image from spilling over the sides of the graph, and generally just looking terrible. However since the image is already being sized for the graph via this line:

    spectrumFill = spectrumFill.scaled(QSize(chart_width*2.5, chart_height));
    

    and set to paint in the top left corner via these lines:

    QPointF TopLeft = splineChart->plotArea().topLeft();
    painter.drawImage(TopLeft, spectrumFill);
    

    I'm not sure it's necessary to do that. I guess it's possible that the rest of the image could default to some ugly color, but I'm not having that problem.

    The solution that I don't like is that my app will never run on a different sized device, at least not how it's been scoped so far. So I can hard-code the size of the image to be whatever I need and move on. I wasn't seeing dynamic resizing of the image depending on the size of the window anyway, so it looks like that would probably be more complex. I'm not going to look into it. So the last piece of code (these are out of order, if you're copying what I'm doing you'll have to look back at my first post in here) sets the image to the size I need, and I can move on.

    int chart_width = static_cast<int>(splineChart->plotArea().width());
    int chart_height = static_cast<int>(splineChart->plotArea().height());
    int view_width = static_cast<int>(splineChartView->width());
    int view_height = static_cast<int>(splineChartView->height());
    spectrumFill = spectrumFill.scaled(QSize(chart_width*2.5, chart_height));
    

    And that does it for me. Good luck to anyone who sees this in the future, I hope you don't need dynamic resizing of your image!
    And thanks QT forum for listening, you're the best coding journal I've ever had. :D


Log in to reply