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. Printing QTextDocument in different thread distorts image.
Forum Updated to NodeBB v4.3 + New Features

Printing QTextDocument in different thread distorts image.

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 2 Posters 523 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.
  • A Offline
    A Offline
    adutzu89
    wrote on last edited by adutzu89
    #1

    Hello,
    I am trying to print with QTextDocument and I have an issue with image aspect ratio when I do the printing using QtConcurrent.

    The image is stretched when printing in different thread, through QtConcurrent::run, but prints correctly when in main thread.

    At first I was loading a html string in the document and when I saw this issue I tried inserting an image dirrectly through QTextCursor but I got the same result.

    I tried using a scaled QImage object and it keeps the image aspect ratio, but it loses a lot of quality, even with Qt::SmoothTransformation.

    Here is the printing method:

    void AbstractEcoForm::printDocument() {
        std::unique_ptr<QTextDocument> printDoc(new QTextDocument);
        std::unique_ptr<QPrinter> printer(new QPrinter);
        printDoc->setPageSize(QSizeF(printer->pageRect().size()));
        setDocumentData(printDoc.get());
        printer->setPrinterName(mCurrentPrinter);
        QString numeDoc = QStringLiteral("Test-print");
        printer->setDocName(numeDoc);
        QPrinterInfo printerInfo(*printer);
        if (printerInfo.isNull()) {
            emit printerError("Nu este setata nici o imprimanta!");
            return;
        }
        if (!printer->isValid()) {
            emit printerError("Imprimanta setata nu este valida!");
            return;
        }
        printDoc->print(printer.get());
        emit printSuccess();
    }
    

    Here is the initial html string for the image :

    <img width=\"300\" src=\"qrc:/assets/logo.png\">
    

    This is my first try with QTextCursor, using QTextImageFormat:

    QTextImageFormat imageFormat;
    imageFormat.setName("qrc:/assets/logo.png");
    imageFormat.setWidth(300);
    cursor.insertImage(imageFormat);
    

    This is my first try with QTextCursor, using QTextImageFormat:

    QImage logo(":/assets/logo.png");
    cursor.insertImage(logo.scaledToWidth(300, Qt::SmoothTransformation));
    

    I am looking for a smooth way to print, without making the application freeze when multiple images are loaded.
    Was printing in an QEventLoop, previously, using web engine but that print method returns a boolean value, QTextDocument doesn't return anything.

    Now I am a bit stuck; any help is much appreciated.

    Environment: Qt 5.12.6, MSVC 2017 32bit, Windows 10 64bit.

    1 Reply Last reply
    0
    • gde23G Offline
      gde23G Offline
      gde23
      wrote on last edited by
      #2

      Just a guess, but when I had some weird problems with scaling it was a timing problem.
      It could be solved by adding small delays using QTimer::Singelshot() to trigger the actual painting of the widgets. So since it depends on the thread this might be some similar case.

      A 1 Reply Last reply
      0
      • gde23G gde23

        Just a guess, but when I had some weird problems with scaling it was a timing problem.
        It could be solved by adding small delays using QTimer::Singelshot() to trigger the actual painting of the widgets. So since it depends on the thread this might be some similar case.

        A Offline
        A Offline
        adutzu89
        wrote on last edited by
        #3

        @gde23 hello, thanks for your answer tried to do a QTimer::singleshot , but with no succes.
        Maybe I did it wrong, could you exmplify a bit what you meant?

        1 Reply Last reply
        0
        • gde23G Offline
          gde23G Offline
          gde23
          wrote on last edited by gde23
          #4

          What I would try is something like this, but as I said its just a guess...

          void AbstractEcoForm::printDocument() {
              std::unique_ptr<QTextDocument> printDoc(new QTextDocument);
              std::unique_ptr<QPrinter> printer(new QPrinter);
              printDoc->setPageSize(QSizeF(printer->pageRect().size()));
              setDocumentData(printDoc.get());
              printer->setPrinterName(mCurrentPrinter);
              QString numeDoc = QStringLiteral("Test-print");
              printer->setDocName(numeDoc);
              QPrinterInfo printerInfo(*printer);
              if (printerInfo.isNull()) {
                  emit printerError("Nu este setata nici o imprimanta!");
                  return;
              }
              if (!printer->isValid()) {
                  emit printerError("Imprimanta setata nu este valida!");
                  return;
              }
              
              QTimer::SingleShot(10, this, SLOT(printTheDocument());
          

          where printTheDocument() is a slot that calls the

          printDoc->print(printer.get());
          

          of your original code

          A 2 Replies Last reply
          1
          • gde23G gde23

            What I would try is something like this, but as I said its just a guess...

            void AbstractEcoForm::printDocument() {
                std::unique_ptr<QTextDocument> printDoc(new QTextDocument);
                std::unique_ptr<QPrinter> printer(new QPrinter);
                printDoc->setPageSize(QSizeF(printer->pageRect().size()));
                setDocumentData(printDoc.get());
                printer->setPrinterName(mCurrentPrinter);
                QString numeDoc = QStringLiteral("Test-print");
                printer->setDocName(numeDoc);
                QPrinterInfo printerInfo(*printer);
                if (printerInfo.isNull()) {
                    emit printerError("Nu este setata nici o imprimanta!");
                    return;
                }
                if (!printer->isValid()) {
                    emit printerError("Imprimanta setata nu este valida!");
                    return;
                }
                
                QTimer::SingleShot(10, this, SLOT(printTheDocument());
            

            where printTheDocument() is a slot that calls the

            printDoc->print(printer.get());
            

            of your original code

            A Offline
            A Offline
            adutzu89
            wrote on last edited by
            #5

            @gde23 said in Printing QTextDocument in different thread distorts image.:

            What I would try is something like this, but as I said its just a guess...

            void AbstractEcoForm::printDocument() {
                std::unique_ptr<QTextDocument> printDoc(new QTextDocument);
                std::unique_ptr<QPrinter> printer(new QPrinter);
                printDoc->setPageSize(QSizeF(printer->pageRect().size()));
                setDocumentData(printDoc.get());
                printer->setPrinterName(mCurrentPrinter);
                QString numeDoc = QStringLiteral("Test-print");
                printer->setDocName(numeDoc);
                QPrinterInfo printerInfo(*printer);
                if (printerInfo.isNull()) {
                    emit printerError("Nu este setata nici o imprimanta!");
                    return;
                }
                if (!printer->isValid()) {
                    emit printerError("Imprimanta setata nu este valida!");
                    return;
                }
                
                QTimer::SingleShot(10, this, SLOT(printTheDocument());
            

            where printTheDocument() is a slot that calls the

            printDoc->print(printer.get());
            

            of your original code

            Holy Qt licensing, it works, I was calling the singleshot inside method where i was adding the elements.
            Thanks a lot!

            1 Reply Last reply
            0
            • gde23G gde23

              What I would try is something like this, but as I said its just a guess...

              void AbstractEcoForm::printDocument() {
                  std::unique_ptr<QTextDocument> printDoc(new QTextDocument);
                  std::unique_ptr<QPrinter> printer(new QPrinter);
                  printDoc->setPageSize(QSizeF(printer->pageRect().size()));
                  setDocumentData(printDoc.get());
                  printer->setPrinterName(mCurrentPrinter);
                  QString numeDoc = QStringLiteral("Test-print");
                  printer->setDocName(numeDoc);
                  QPrinterInfo printerInfo(*printer);
                  if (printerInfo.isNull()) {
                      emit printerError("Nu este setata nici o imprimanta!");
                      return;
                  }
                  if (!printer->isValid()) {
                      emit printerError("Imprimanta setata nu este valida!");
                      return;
                  }
                  
                  QTimer::SingleShot(10, this, SLOT(printTheDocument());
              

              where printTheDocument() is a slot that calls the

              printDoc->print(printer.get());
              

              of your original code

              A Offline
              A Offline
              adutzu89
              wrote on last edited by adutzu89
              #6

              @gde23 said in Printing QTextDocument in different thread distorts image.:

              What I would try is something like this, but as I said its just a guess...

              void AbstractEcoForm::printDocument() {
                  std::unique_ptr<QTextDocument> printDoc(new QTextDocument);
                  std::unique_ptr<QPrinter> printer(new QPrinter);
                  printDoc->setPageSize(QSizeF(printer->pageRect().size()));
                  setDocumentData(printDoc.get());
                  printer->setPrinterName(mCurrentPrinter);
                  QString numeDoc = QStringLiteral("Test-print");
                  printer->setDocName(numeDoc);
                  QPrinterInfo printerInfo(*printer);
                  if (printerInfo.isNull()) {
                      emit printerError("Nu este setata nici o imprimanta!");
                      return;
                  }
                  if (!printer->isValid()) {
                      emit printerError("Imprimanta setata nu este valida!");
                      return;
                  }
                  
                  QTimer::SingleShot(10, this, SLOT(printTheDocument());
              

              where printTheDocument() is a slot that calls the

              printDoc->print(printer.get());
              

              of your original code

              And I'm back :D, seems while the code somehow works and the app doesn't crash I get the following warning:

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

              Edit:: I gave up on QtConcurrent and went with QueuedConnection connection.
              Thank you.

              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