Printing QTextDocument in different thread distorts image.
-
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.
-
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. -
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. -
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
-
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
@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! -
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
@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.