Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QTextDocument in thread issue
Forum Updated to NodeBB v4.3 + New Features

QTextDocument in thread issue

Scheduled Pinned Locked Moved Solved General and Desktop
22 Posts 5 Posters 2.3k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Cobra91151C Offline
    Cobra91151C Offline
    Cobra91151
    wrote on last edited by Cobra91151
    #1

    Hello!

    I want to display the print preview dialog with some data before printing. The data is very big, so it freezes. I have added it to a thread and added the progress dialog but the progress dialog seems also freeze. I have found the issue is with QTextDocument setPlainText method in GUI (main thread). So, I added it in the thread as well.

    I created the QTextDocument object in the thread, setPlainText("some data") there. Now, I have issue when I emit QTextDocument object from a worker class to use it in main thread in the following lambda connect:

    connect(printPreviewDlg, &QPrintPreviewDialog::paintRequested, this, [txtDoc](QPrinter *printer) {
            txtDoc->print(printer);
    });
    

    It crashes with a read access violation error. I need this object to call print method in QPrintPreviewDialog connect. Any ideas/examples how to send QTextDocument object between worker/main GUI threads properly? Thank you.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Are you sure txtDoc is a valid pointer ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      Cobra91151C 1 Reply Last reply
      0
      • Cobra91151C Offline
        Cobra91151C Offline
        Cobra91151
        wrote on last edited by
        #3

        From this docs: https://doc.qt.io/qt-5/threads-modules.html I have found that I can pass a copy between threads by using the clone method. I tried it but it returns:

        QObject: Cannot create children for a parent that is in a different thread.
        (Parent is QTextDocument(0x2314adccdf0), parent's thread is QThread(0x2314b524020), current thread is QThread(0x23139204630)
        
        1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          Are you sure txtDoc is a valid pointer ?

          Cobra91151C Offline
          Cobra91151C Offline
          Cobra91151
          wrote on last edited by
          #4

          @SGaist

          Yes, it is valid. I initialized it, set the data and emit it from a worker.

          Code:

          QFont docFont;
          docFont.setPointSize(14);
          QTextDocument *textDoc = new QTextDocument(this);
          textDoc->setDefaultFont(docFont);
          textDoc->setPlainText("some data");
          emit generatedPreview(textDoc); // crashes in the slot
          
          emit generatedPreviewData(textDoc->clone()); //works but returns QObject: Cannot create children for a parent that is in a different thread. (Parent is QTextDocument(0x2314adccdf0), parent's thread is QThread(0x2314b524020), current thread is QThread(0x23139204630)
          
          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Why not create the QTextDocument in your thread and then move it to the main thread once it's ready ?

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            Cobra91151C 1 Reply Last reply
            0
            • SGaistS SGaist

              Why not create the QTextDocument in your thread and then move it to the main thread once it's ready ?

              Cobra91151C Offline
              Cobra91151C Offline
              Cobra91151
              wrote on last edited by Cobra91151
              #6

              @SGaist said in QTextDocument in thread issue:

              Why not create the QTextDocument in your thread and then move it to the main thread once it's ready ?

              What do you mean by your thread? I created it in a worker class and emit it to the main thread, then it crashes. When I pass it from a worker to main thread as a clone it displays the following issue: QObject: Cannot create children for a parent that is in a different thread..

              I can create QTextDocument object in the main thread, pass it to worker, setPlainText there and then emit QTextDocument object back to main thread?

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                If by passing you mean updating a pointer value, then you are not moving things around.

                Since QTextDocument is a QObject, hence the suggestion of using moveToThread.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                Cobra91151C 1 Reply Last reply
                0
                • SGaistS SGaist

                  If by passing you mean updating a pointer value, then you are not moving things around.

                  Since QTextDocument is a QObject, hence the suggestion of using moveToThread.

                  Cobra91151C Offline
                  Cobra91151C Offline
                  Cobra91151
                  wrote on last edited by
                  #8

                  @SGaist

                  So, I should call moveToThread on QTextDocument object in a worker or in main GUI? Thanks.

                  eyllanescE 1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    Since you create it in your secondary thread, you need to push it to your main thread.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    0
                    • Cobra91151C Cobra91151

                      @SGaist

                      So, I should call moveToThread on QTextDocument object in a worker or in main GUI? Thanks.

                      eyllanescE Offline
                      eyllanescE Offline
                      eyllanesc
                      wrote on last edited by
                      #10

                      @Cobra91151 QTextDocument should not live in a second thread so you get that error. QTextDocument will interact with QObjects that live in the main thread (for example QTextEdit, QPrinter, etc).

                      If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

                      Cobra91151C 2 Replies Last reply
                      0
                      • eyllanescE eyllanesc

                        @Cobra91151 QTextDocument should not live in a second thread so you get that error. QTextDocument will interact with QObjects that live in the main thread (for example QTextEdit, QPrinter, etc).

                        Cobra91151C Offline
                        Cobra91151C Offline
                        Cobra91151
                        wrote on last edited by
                        #11

                        @SGaist @eyllanesc

                        From this old post, I can use QTextDocument object in worker class (second thread) and pass it between the threads: https://www.qt.io/blog/2007/09/27/multi-threaded-text-layout-and-printing

                        It contains the old thread design but I want to check out the full source code. Where I can find this snapshot example? Thank you.

                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          Based on the name, I would go with the Qt 4 sources of Assistant.

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          1 Reply Last reply
                          0
                          • eyllanescE eyllanesc

                            @Cobra91151 QTextDocument should not live in a second thread so you get that error. QTextDocument will interact with QObjects that live in the main thread (for example QTextEdit, QPrinter, etc).

                            Cobra91151C Offline
                            Cobra91151C Offline
                            Cobra91151
                            wrote on last edited by
                            #13

                            @eyllanesc said in QTextDocument in thread issue:

                            @Cobra91151 QTextDocument should not live in a second thread so you get that error. QTextDocument will interact with QObjects that live in the main thread (for example QTextEdit, QPrinter, etc).

                            @eyllanesc

                            I had QTextDocument in my main thread but setPlainText method freezes the GUI for a couple of seconds. So, I need to fix it. That is why I put it to the worker (second thread). Thanks.

                            jsulmJ 1 Reply Last reply
                            0
                            • Cobra91151C Cobra91151

                              @eyllanesc said in QTextDocument in thread issue:

                              @Cobra91151 QTextDocument should not live in a second thread so you get that error. QTextDocument will interact with QObjects that live in the main thread (for example QTextEdit, QPrinter, etc).

                              @eyllanesc

                              I had QTextDocument in my main thread but setPlainText method freezes the GUI for a couple of seconds. So, I need to fix it. That is why I put it to the worker (second thread). Thanks.

                              jsulmJ Offline
                              jsulmJ Offline
                              jsulm
                              Lifetime Qt Champion
                              wrote on last edited by
                              #14

                              @Cobra91151 Qt UI classes should not be used in other threads than main (UI) thread!
                              How big is the text you're trying to load?

                              https://forum.qt.io/topic/113070/qt-code-of-conduct

                              Cobra91151C 1 Reply Last reply
                              1
                              • jsulmJ jsulm

                                @Cobra91151 Qt UI classes should not be used in other threads than main (UI) thread!
                                How big is the text you're trying to load?

                                Cobra91151C Offline
                                Cobra91151C Offline
                                Cobra91151
                                wrote on last edited by
                                #15

                                @jsulm

                                It is 280 pages for printing. I run some debugging and found out that setPlainText does not lead to such issue. The actual problem is with print method. It takes too much time to paint all these pages to the QPrintPreviewDialog.

                                Code:

                                connect(printPreviewDlg, &QPrintPreviewDialog::paintRequested, this, [txtDoc](QPrinter *printer) {
                                        txtDoc->print(printer);
                                });
                                

                                I will subclass the QTextDocument and reimplement the print method to display some progress dialog. Thanks.

                                1 Reply Last reply
                                0
                                • Cobra91151C Offline
                                  Cobra91151C Offline
                                  Cobra91151
                                  wrote on last edited by
                                  #16

                                  Nope, it does not work. The progress dialog still freezing.

                                  jsulmJ 1 Reply Last reply
                                  0
                                  • Cobra91151C Cobra91151

                                    Nope, it does not work. The progress dialog still freezing.

                                    jsulmJ Offline
                                    jsulmJ Offline
                                    jsulm
                                    Lifetime Qt Champion
                                    wrote on last edited by
                                    #17

                                    @Cobra91151 Can you show ther code?

                                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                                    Cobra91151C 1 Reply Last reply
                                    0
                                    • jsulmJ jsulm

                                      @Cobra91151 Can you show ther code?

                                      Cobra91151C Offline
                                      Cobra91151C Offline
                                      Cobra91151
                                      wrote on last edited by
                                      #18

                                      @jsulm

                                      Yes, I will create the test example and post it soon. Thank you.

                                      JonBJ 1 Reply Last reply
                                      0
                                      • Cobra91151C Cobra91151

                                        @jsulm

                                        Yes, I will create the test example and post it soon. Thank you.

                                        JonBJ Offline
                                        JonBJ Offline
                                        JonB
                                        wrote on last edited by JonB
                                        #19

                                        @Cobra91151
                                        Also for 280 pages just how long does it take/freeze? Oh you said "a couple of seconds". Does your end-user not have the patience to wait 2 seconds for 280 pages? :) If the user prints to printer how long does it take? Users are over-pampered these days....

                                        Cobra91151C 1 Reply Last reply
                                        0
                                        • JonBJ JonB

                                          @Cobra91151
                                          Also for 280 pages just how long does it take/freeze? Oh you said "a couple of seconds". Does your end-user not have the patience to wait 2 seconds for 280 pages? :) If the user prints to printer how long does it take? Users are over-pampered these days....

                                          Cobra91151C Offline
                                          Cobra91151C Offline
                                          Cobra91151
                                          wrote on last edited by
                                          #20

                                          @jsulm @JonB

                                          Here is my test example:

                                          printexample.h

                                          #ifndef PRINTEXAMPLE_H
                                          #define PRINTEXAMPLE_H
                                          
                                          #include <QWidget>
                                          #include <QPushButton>
                                          #include <QHBoxLayout>
                                          #include <QThread>
                                          #include <QPrinter>
                                          #include <QPrintPreviewDialog>
                                          #include <QToolBar>
                                          #include <QTextDocument>
                                          #include <QDebug>
                                          #include "printworker.h"
                                          
                                          class PrintExample : public QWidget
                                          {
                                              Q_OBJECT
                                          
                                          public:
                                              PrintExample(QWidget *parent = nullptr);
                                              ~PrintExample();
                                          
                                          private slots:
                                              void printData();
                                              void setPrintPreviewData(QString printData);
                                              void setPreviewDataGenerationFailed();
                                          
                                          private:
                                              QLayout *printLayout(QPushButton *btn);
                                          };
                                          #endif // PRINTEXAMPLE_H
                                          

                                          printexample.cpp

                                          #include "printexample.h"
                                          
                                          PrintExample::PrintExample(QWidget *parent)
                                              : QWidget(parent)
                                          {
                                              setWindowTitle("Print example");
                                              setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
                                              setFixedSize(500, 400);
                                              QPushButton *printBtn = new QPushButton("Print", this);
                                              printBtn->setFixedSize(120, 50);
                                              connect(printBtn, &QPushButton::clicked, this, &PrintExample::printData);
                                              setLayout(printLayout(printBtn));
                                          }
                                          
                                          QLayout *PrintExample::printLayout(QPushButton *btn)
                                          {
                                              QHBoxLayout *btnLayout = new QHBoxLayout();
                                              btnLayout->setAlignment(Qt::AlignHCenter);
                                              btnLayout->addWidget(btn);
                                              return btnLayout;
                                          }
                                          
                                          void PrintExample::printData()
                                          {
                                              //This is just test example data
                                              QString testBigData = "QTextDocument is a container for structured rich text documents, providing support for styled text and various types of document elements, such as lists, tables, "
                                                                    "frames, and images. They can be created for use in a QTextEdit, or used independently. Each document element is described by an associated format object. "
                                                                    "Each format object is treated as a unique object by QTextDocuments, and can be passed to objectForFormat() to obtain the document element that it is applied to. "
                                                                    "A QTextDocument can be edited programmatically using a QTextCursor, and its contents can be examined by traversing the document structure. "
                                                                    "The entire document structure is stored as a hierarchy of document elements beneath the root frame, found with the rootFrame() function. "
                                                                    "Alternatively, if you just want to iterate over the textual contents of the document you can use begin(), end(), and findBlock() to retrieve text blocks that you can "
                                                                    "examine and iterate over. The layout of a document is determined by the documentLayout(); you can create your own QAbstractTextDocumentLayout subclass and set it using "
                                                                    "setDocumentLayout() if you want to use your own layout logic. The document's title and other meta-information can be obtained by calling the metaInformation() "
                                                                    "function. For documents that are exposed to users through the QTextEdit class, the document title is also available via the QTextEdit::documentTitle() "
                                                                    "function. The toPlainText() and toHtml() convenience functions allow you to retrieve the contents of the document as plain text and HTML. "
                                                                    "The document's text can be searched using the find() functions. Undo/redo of operations performed on the document can be controlled using the setUndoRedoEnabled() "
                                                                    "function. The undo/redo system can be controlled by an editor widget through the undo() and redo() slots; the document also provides contentsChanged(), "
                                                                    "undoAvailable(), and redoAvailable() signals that inform connected editor widgets about the state of the undo/redo system. "
                                                                    "The following are the undo/redo operations of a QTextDocument.";
                                              QThread *printDataThread = new QThread();
                                              PrintWorker *printWorker = new PrintWorker();
                                              printWorker->moveToThread(printDataThread);
                                              connect(printWorker, &PrintWorker::generatedPreviewData, this, &PrintExample::setPrintPreviewData);
                                              connect(printWorker, &PrintWorker::previewDataGenerationFailed, this, &PrintExample::setPreviewDataGenerationFailed);
                                              connect(printWorker, &PrintWorker::finished, printDataThread, &QThread::quit);
                                              connect(printWorker, &PrintWorker::finished, printWorker, &PrintWorker::deleteLater);
                                              connect(printDataThread, &QThread::finished, printDataThread, &QThread::deleteLater);
                                              QMetaObject::invokeMethod(printWorker, "generatePrintPreview", Q_ARG(QString, testBigData));
                                              printDataThread->start();
                                          }
                                          
                                          void PrintExample::setPrintPreviewData(QString printData)
                                          {
                                              QPrinter *previewPrinter = new QPrinter(QPrinter::HighResolution);
                                              previewPrinter->setOutputFormat(QPrinter::NativeFormat);
                                              previewPrinter->setPaperSize(QPrinter::A4);
                                              previewPrinter->setPageMargins(QMarginsF(15, 15, 15, 15));
                                              QPrintPreviewDialog *printPreviewDlg = new QPrintPreviewDialog(previewPrinter, this);
                                              printPreviewDlg->setGeometry(100, 100, 700, 500);
                                              printPreviewDlg->setMinimumSize(700, 500);
                                              printPreviewDlg->setWindowModality(Qt::ApplicationModal);
                                              printPreviewDlg->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
                                              printPreviewDlg->installEventFilter(this);
                                              QFont docFont;
                                              docFont.setPointSize(14);
                                              QTextDocument *textDoc = new QTextDocument(this);
                                              textDoc->setDefaultFont(docFont);
                                              textDoc->setPlainText(printData);
                                              connect(printPreviewDlg, &QPrintPreviewDialog::paintRequested, this, [this, textDoc](QPrinter *printer) {
                                                  textDoc->print(printer);
                                              });
                                              connect(printPreviewDlg, &QPrintPreviewDialog::finished, this, [textDoc, previewPrinter, printPreviewDlg]() {
                                                  textDoc->deleteLater();
                                                  delete previewPrinter;
                                                  printPreviewDlg->deleteLater();
                                              });
                                              printPreviewDlg->show();
                                          }
                                          
                                          void PrintExample::setPreviewDataGenerationFailed()
                                          {
                                              //Failed to generate preview
                                          }
                                          
                                          PrintExample::~PrintExample()
                                          {
                                          
                                          }
                                          

                                          printworker.h:

                                          #ifndef PRINTWORKER_H
                                          #define PRINTWORKER_H
                                          
                                          #include <QObject>
                                          
                                          class PrintWorker : public QObject
                                          {
                                              Q_OBJECT
                                          public:
                                              explicit PrintWorker(QObject *parent = nullptr);
                                          
                                          public slots:
                                              void generatePrintPreview(QString previewData);
                                          
                                          signals:
                                              void generatedPreviewData(QString data);
                                              void previewDataGenerationFailed();
                                              void finished();
                                          };
                                          
                                          #endif // PRINTWORKER_H
                                          

                                          printworker.cpp:

                                          #include "printworker.h"
                                          
                                          PrintWorker::PrintWorker(QObject *parent) : QObject(parent)
                                          {
                                          
                                          }
                                          
                                          void PrintWorker::generatePrintPreview(QString previewData)
                                          {
                                              if (!previewData.isEmpty()) {
                                                  emit generatedPreviewData(previewData);
                                              } else {
                                                  emit previewDataGenerationFailed();
                                              }
                                          
                                              emit finished();
                                          }
                                          

                                          Screenshot:
                                          alt text

                                          So, it does not freeze much for 1 page. Anyway, I want to display some progress dialog before the preview dialog. Any ideas? Thanks.

                                          jsulmJ 1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved