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.

Printing QTextDocument in different thread distorts image.

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 2 Posters 449 Views
  • 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