Search code examples
c++qtgantt-chartqtcharts

QT Chart doesn't fill entire ChartView causing a mirroring effect


I am essentially trying to make a Gantt Chart in Qt. I was going to plot bars on a image. I am able to plot a Bar(green) starting at the beginning of a Chart but I also get a second Bar(green) closer to the end of the Chart. I think the plottable area of the Chart doesn't fill up the entire ChartView so it's doing some kind of repeated fill of the missing data(MAYBE?). Was hoping someone could tell me what I'm doing wrong. QT version 5.15.0.

    ui.setupUi(parent);
    QGridLayout *gridLayout = new QGridLayout(ui.widget);

    //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);

    // ===== CHART VIEWER ===== //
    // Create a Chart Viewer:
    QtCharts::QChartView* chartView = new QtCharts::QChartView();
    // Add widget to GUI:
    gridLayout->addWidget(chartView);
    //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
    chart->setPlotArea(QRectF());

    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());

    //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::gray);
    QPainter painter(&translated);
    QPointF TopLeft = chart->plotArea().topLeft();
    QPointF BotRight = chart->plotArea().bottomRight();
    painter.fillRect(TopLeft.x(), TopLeft.y(), 10, BotRight.y() - TopLeft.y(), Qt::green);

    //Display image in background
    chart->setPlotAreaBackgroundBrush(translated);
    chart->setPlotAreaBackgroundVisible(true);

enter image description here


Solution

  • I made the 2 changes:

    1. paint the background in a slot function.
    2. emit the slotAreaChanged signal.

    Here is the code

    #include<QGridLayout>
    #include<QLineSeries>
    #include<QChartView>
    #include<QChart>
    #include<QApplication>
    
    int main()
    {
        int a = 0;
        QApplication b(a, nullptr);
        QWidget w;
        QGridLayout* gridLayout = new QGridLayout();
    
        //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);
    
        // ===== CHART VIEWER ===== //
        // Create a Chart Viewer:
        QtCharts::QChartView* chartView = new QtCharts::QChartView();
        // Add widget to GUI:
        gridLayout->addWidget(chartView);
        //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
        chart->setPlotArea(QRectF());
    
        QObject::connect(chart, &QtCharts::QChart::plotAreaChanged, [&](const QRectF& plotArea) {
    
        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());
    
        //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::gray);
        QPainter painter(&translated);
        QPointF TopLeft = chart->plotArea().topLeft();
        QPointF BotRight = chart->plotArea().bottomRight();
        painter.fillRect(TopLeft.x(), TopLeft.y(), 10, BotRight.y() - TopLeft.y(), Qt::green);
    
        //Display image in background
        chart->setPlotAreaBackgroundBrush(translated);
        chart->setPlotAreaBackgroundVisible(true);
    });
        w.setLayout(gridLayout);
        chart->plotAreaChanged(QRectF());
        w.show();
        return b.exec();
    }