0

In this code example two buttons are created:

  • The first one displays a graph in a new window
  • The second one prints a graph in another thread to make concurrent use and not hurt the main thread (it is not the case of the example but it could take a long time in generating the data for the graph).
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QtConcurrent/QtConcurrent>
#include <QHBoxLayout>
#include <QChartView>
#include <QLineSeries>
#include <QValueAxis>
#include <QChart>
#include <QDebug>
#include <QPrintEngine>

class ChartWidget : public QWidget {
    Q_OBJECT
public:
    ChartWidget(QWidget *parent = nullptr) : QWidget(parent) {
        QtCharts::QChart *chart = new QtCharts::QChart;
        QtCharts::QLineSeries *series = new QtCharts::QLineSeries;
        for (int i = 0; i < 10; ++i)
            series->append(i, qrand() % 100);

        chart->addSeries(series);

        QtCharts::QValueAxis *axisX = new QtCharts::QValueAxis;
        QtCharts::QValueAxis *axisY = new QtCharts::QValueAxis;
        chart->addAxis(axisX, Qt::AlignBottom);
        chart->addAxis(axisY, Qt::AlignLeft);
        series->attachAxis(axisX);
        series->attachAxis(axisY);

        QtCharts::QChartView *chartView = new QtCharts::QChartView(chart);
        QHBoxLayout *layout = new QHBoxLayout;
        layout->addWidget(chartView);
        setLayout(layout);
    }
    ~ChartWidget() {
        close();
    }
    void printChart() {
        QPrinter *Printer=new QPrinter();
        QPainter *Painter=new QPainter();
        Printer->setOutputFormat(QPrinter::PdfFormat);
        Printer->setOutputFileName("/tmp/test.pdf");
        Painter->begin(Printer);
        this->render(Painter);
        Painter->end();
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QPushButton *button1=new QPushButton("Main Th");
    QPushButton *button2=new QPushButton("Concurrent Th");

    QWidget *window=new QWidget;
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(button1);
    layout->addWidget(button2);
    window->setLayout(layout);
    window->show();


    QObject::connect(button1, &QPushButton::clicked, []() {
        ChartWidget *W=new ChartWidget();
        W->show();
    });

    QObject::connect(button2, &QPushButton::clicked, []() {

        QtConcurrent::run([](){
            ChartWidget *W=new ChartWidget();
            W->printChart();
        });

    });

    return app.exec();

}

#include "main.moc"

In the same execution we can make use of the first or second button repeatedly without any problem, but if we alternate them an error is raised.

The object is independently instanced for each button and have a local scope.

The error:

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument (0x5591bd230840), 
parent's thread is QThread (0x5591bc402810), 
current thread is QThread (0x7f3ad400ba10)

or similar one is raised.

How to fix it?

Jss
  • 1

0 Answers0