Async and QPainter, printing function
-
Hi, im working a printer function and manage to print all the info i need using a Qpainter event, the problem is the bigger the data i send the longer it takes to print and it have the tendency to freeze my program i did try using async from the standart C++ library but it seems its not compatible, theres any way to use Qpainter without freezing my program?
i add my code, i call this function
Imprimir_Registros
everytime i want to print, i pass the qwidget so it can actually works and a vector that holds all my actual data, the problem is when im printing several pages the function can lag for several secondsImp_RegIndiv_Boletas
its where all the printing happends using qpainter, it expects 3 parameters Qpainter, Vector and Number of pagesvoid Impresora::Imprimir_Registros ( QWidget *parent, const std::vector<Data> &print ){ QPrintDialog dialog(parent); dialog.setWindowTitle("Impresion de Boletas"); printer = dialog.printer(); printer->setFullPage(true); printer->setPaperSize(QPrinter::Letter); Qpainter Imp(printer); Imp.scale(0.97, 0.97); if ( print.size() > 12){ NoPage = print.size() / 15; for ( auto j {0}; j < NoPage+1 ; j++ ){ // std::async(std::launch::async, Imp_RegIndiv_Boletas, Imp, print, j ); <--- did try this but its not compatible Imp_RegIndiv_Boletas(Imp, print); if ( j < NoPage ) { printer ->newPage(); } } } else { Imp_RegIndiv_Boletas(Imp, print, 0); } }
-
Hi, im working a printer function and manage to print all the info i need using a Qpainter event, the problem is the bigger the data i send the longer it takes to print and it have the tendency to freeze my program i did try using async from the standart C++ library but it seems its not compatible, theres any way to use Qpainter without freezing my program?
i add my code, i call this function
Imprimir_Registros
everytime i want to print, i pass the qwidget so it can actually works and a vector that holds all my actual data, the problem is when im printing several pages the function can lag for several secondsImp_RegIndiv_Boletas
its where all the printing happends using qpainter, it expects 3 parameters Qpainter, Vector and Number of pagesvoid Impresora::Imprimir_Registros ( QWidget *parent, const std::vector<Data> &print ){ QPrintDialog dialog(parent); dialog.setWindowTitle("Impresion de Boletas"); printer = dialog.printer(); printer->setFullPage(true); printer->setPaperSize(QPrinter::Letter); Qpainter Imp(printer); Imp.scale(0.97, 0.97); if ( print.size() > 12){ NoPage = print.size() / 15; for ( auto j {0}; j < NoPage+1 ; j++ ){ // std::async(std::launch::async, Imp_RegIndiv_Boletas, Imp, print, j ); <--- did try this but its not compatible Imp_RegIndiv_Boletas(Imp, print); if ( j < NoPage ) { printer ->newPage(); } } } else { Imp_RegIndiv_Boletas(Imp, print, 0); } }
@Lightshadown said in Async and QPainter, printing function:
i did try using async from the standart C++ library but it seems its not compatible
What are the symptoms of the incompatibility?
i add my code, i call this function
Imprimir_Registros
everytime i want to print, i pass the qwidget so it can actually works and a vector that holds all my actual data, the problem is when im printing several pages the function can lag for several secondsImp_RegIndiv_Boletas
its where all the printing happends using qpainter, it expects 3 parameters Qpainter, Vector and Number of pagesvoid Impresora::Imprimir_Registros ( QWidget *parent, const std::vector<Data> &print ){ QPrintDialog dialog(parent); dialog.setWindowTitle("Impresion de Boletas"); printer = dialog.printer();
What is
printer
's type and scope?printer->setFullPage(true); printer->setPaperSize(QPrinter::Letter); Qpainter Imp(printer);
This goes out of scope at the end of the function, which may be before the std::async tasks completes if/when that part works as an async rather than deferred task. Scope may also be an issue for
std::vector<Data> &print
.Imp.scale(0.97, 0.97); if ( print.size() > 12){ NoPage = print.size() / 15; for ( auto j {0}; j < NoPage+1 ; j++ ){ // std::async(std::launch::async, Imp_RegIndiv_Boletas, Imp, print, j ); <--- did try this but its not compatible
This seems unlikely to work as desired for multiple pages. QPainter is reentrant, but not thread-safe. Even if it was, what does printing multiple pages to one printer concurrently mean? A better strategy would be to pass the entire set of pages, or delay submitting each block until its predecessor completes.
-
Qt has its own multithreading API.
https://doc.qt.io/qt-5/qthread.html -
@Lightshadown said in Async and QPainter, printing function:
i did try using async from the standart C++ library but it seems its not compatible
What are the symptoms of the incompatibility?
i add my code, i call this function
Imprimir_Registros
everytime i want to print, i pass the qwidget so it can actually works and a vector that holds all my actual data, the problem is when im printing several pages the function can lag for several secondsImp_RegIndiv_Boletas
its where all the printing happends using qpainter, it expects 3 parameters Qpainter, Vector and Number of pagesvoid Impresora::Imprimir_Registros ( QWidget *parent, const std::vector<Data> &print ){ QPrintDialog dialog(parent); dialog.setWindowTitle("Impresion de Boletas"); printer = dialog.printer();
What is
printer
's type and scope?printer->setFullPage(true); printer->setPaperSize(QPrinter::Letter); Qpainter Imp(printer);
This goes out of scope at the end of the function, which may be before the std::async tasks completes if/when that part works as an async rather than deferred task. Scope may also be an issue for
std::vector<Data> &print
.Imp.scale(0.97, 0.97); if ( print.size() > 12){ NoPage = print.size() / 15; for ( auto j {0}; j < NoPage+1 ; j++ ){ // std::async(std::launch::async, Imp_RegIndiv_Boletas, Imp, print, j ); <--- did try this but its not compatible
This seems unlikely to work as desired for multiple pages. QPainter is reentrant, but not thread-safe. Even if it was, what does printing multiple pages to one printer concurrently mean? A better strategy would be to pass the entire set of pages, or delay submitting each block until its predecessor completes.
What are the symptoms of the incompatibility?
basically i got 3 problems as follows, first it saids "this" was not capture for the lamda, not sure if it refers to the widget that im actually passing already.
then it saids i cannot call the function whitout elements, and finally it saids im calling a deleted functionImpresora.cpp:76:96: error: 'this' was not captured for this lambda function 76 | std::async(std::launch::async, [Imp, print, j](){Imp_RegIndiv_Boletas(Imp, print, j);} ); | ^ Impresora.cpp:76:96: error: cannot call member function 'void Impresora::Imp_RegIndiv_Boletas(QPainter&, const std::vector<Data>&, int)' without object Impresora.cpp: In member function 'void Impresora::imprimir_RegInd(QWidget*, const std::vector<Data>&)': Impresora.cpp:76:44: error: use of deleted function 'QPainter::QPainter(const QPainter&)' 76 | std::async(std::launch::async, [Imp, print, j](){Imp_RegIndiv_Boletas(Imp, print, j);} ); |
forgot to add the declaration from printer
QPrinter *printer;
What is
printer
's type and scope?printer->setFullPage(true); printer->setPaperSize(QPrinter::Letter); Qpainter Imp(printer);
I do it this way so i can pass only the elements that fits inside the page, 15 in my case, you said it would be out of scope but the idea its to call the function and place the diferent pages on the printer, it already works without the async, how can i handle it then?
This goes out of scope at the end of the function, which may be before the std::async tasks completes if/when that part works as an async rather than deferred task. Scope may also be an issue for
std::vector<Data> &print
.Imp.scale(0.97, 0.97); if ( print.size() > 12){ NoPage = print.size() / 15; for ( auto j {0}; j < NoPage+1 ; j++ ){ // std::async(std::launch::async, Imp_RegIndiv_Boletas, Imp, print, j ); <--- did try this but its not compatible
meabe calling not the function but the if inside a lambda thats been called from the async function perhaps, that way it behaves like it already its working but running on a separate thread
This seems unlikely to work as desired for multiple pages. QPainter is reentrant, but not thread-safe. Even if it was, what does printing multiple pages to one printer concurrently mean? A better strategy would be to pass the entire set of pages, or delay submitting each block until its predecessor completes.
Edit: ok did try the follow code using async and a lambda (basically just throw the if inside the lambda), oddly it insist that im using a deleted qpainter object, but wont let me assing it properly, not sure what im missing here
Edit2: i forgot to pass by reference the arguments of tha lambda so now i dont get a deleted function issue, but now it said "this cannot be capture for this lambda" and "cannot call function without object" on the printing function Imp_RegIndv_Boletas
edit3: i decided to pass all elemnts by reference to the lambda and it kinda works
std::async(std::launch::async, [&]()
but the problem now is apparently mingw32 wont work with future as stated here https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64735 , async starts to kill me nerves, if this wont work i guess will try qtthreads and see what happendsstd::async(std::launch::async, [&Imp, &print, &printer](){ Silo* silo = new Silo; int NoPage{0}; if( print.size()>12 ){ silo->Log("Mayor a 12 elementos " + QString::number(print.size())); NoPage = print.size() / 15; for (auto j{0}; j<NoPage+1 ;j++) { Imp_RegIndiv_Boletas(Imp, print, j); if(j<NoPage) {printer->newPage();} } }else{ Imp_RegIndiv_Boletas(Imp, print, 0); } });
-
What are the symptoms of the incompatibility?
basically i got 3 problems as follows, first it saids "this" was not capture for the lamda, not sure if it refers to the widget that im actually passing already.
then it saids i cannot call the function whitout elements, and finally it saids im calling a deleted functionImpresora.cpp:76:96: error: 'this' was not captured for this lambda function 76 | std::async(std::launch::async, [Imp, print, j](){Imp_RegIndiv_Boletas(Imp, print, j);} ); | ^ Impresora.cpp:76:96: error: cannot call member function 'void Impresora::Imp_RegIndiv_Boletas(QPainter&, const std::vector<Data>&, int)' without object Impresora.cpp: In member function 'void Impresora::imprimir_RegInd(QWidget*, const std::vector<Data>&)': Impresora.cpp:76:44: error: use of deleted function 'QPainter::QPainter(const QPainter&)' 76 | std::async(std::launch::async, [Imp, print, j](){Imp_RegIndiv_Boletas(Imp, print, j);} ); |
forgot to add the declaration from printer
QPrinter *printer;
What is
printer
's type and scope?printer->setFullPage(true); printer->setPaperSize(QPrinter::Letter); Qpainter Imp(printer);
I do it this way so i can pass only the elements that fits inside the page, 15 in my case, you said it would be out of scope but the idea its to call the function and place the diferent pages on the printer, it already works without the async, how can i handle it then?
This goes out of scope at the end of the function, which may be before the std::async tasks completes if/when that part works as an async rather than deferred task. Scope may also be an issue for
std::vector<Data> &print
.Imp.scale(0.97, 0.97); if ( print.size() > 12){ NoPage = print.size() / 15; for ( auto j {0}; j < NoPage+1 ; j++ ){ // std::async(std::launch::async, Imp_RegIndiv_Boletas, Imp, print, j ); <--- did try this but its not compatible
meabe calling not the function but the if inside a lambda thats been called from the async function perhaps, that way it behaves like it already its working but running on a separate thread
This seems unlikely to work as desired for multiple pages. QPainter is reentrant, but not thread-safe. Even if it was, what does printing multiple pages to one printer concurrently mean? A better strategy would be to pass the entire set of pages, or delay submitting each block until its predecessor completes.
Edit: ok did try the follow code using async and a lambda (basically just throw the if inside the lambda), oddly it insist that im using a deleted qpainter object, but wont let me assing it properly, not sure what im missing here
Edit2: i forgot to pass by reference the arguments of tha lambda so now i dont get a deleted function issue, but now it said "this cannot be capture for this lambda" and "cannot call function without object" on the printing function Imp_RegIndv_Boletas
edit3: i decided to pass all elemnts by reference to the lambda and it kinda works
std::async(std::launch::async, [&]()
but the problem now is apparently mingw32 wont work with future as stated here https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64735 , async starts to kill me nerves, if this wont work i guess will try qtthreads and see what happendsstd::async(std::launch::async, [&Imp, &print, &printer](){ Silo* silo = new Silo; int NoPage{0}; if( print.size()>12 ){ silo->Log("Mayor a 12 elementos " + QString::number(print.size())); NoPage = print.size() / 15; for (auto j{0}; j<NoPage+1 ;j++) { Imp_RegIndiv_Boletas(Imp, print, j); if(j<NoPage) {printer->newPage();} } }else{ Imp_RegIndiv_Boletas(Imp, print, 0); } });
@Lightshadown said in Async and QPainter, printing function:
this cannot be capture for this lambda" and "cannot call function without objec
If you want to access class members/methods inside the lambda you have to capture "this".
-
@Lightshadown said in Async and QPainter, printing function:
this cannot be capture for this lambda" and "cannot call function without objec
If you want to access class members/methods inside the lambda you have to capture "this".
@jsulm actually i decided to pass all elements into the lambda
std::async(std::launch::async, [&] ( ) )
but for some reason it said its not compatible with my compiler, it said im using an incomplete function type
Im looking into Qt threats to see if i can do async workImpresora.cpp: In member function 'void Impresora::imprimir_RegInd(QWidget*, const std::vector<Data>&)': Impresora.cpp:98:6: error: invalid use of incomplete type 'class std::future<void>' 98 | }); | ^ In file included from Impresora.cpp:13: c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\future:125:11: note: declaration of 'class std::future<void>' 125 | class future; | ^~~~~~ c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\future: At global scope: c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\future:189:5: error: 'std::future<typename std::__invoke_result<typename std::decay<_Tp>::type, typename std::decay<_Args>::type ...>::type> std::async(std::launch, _Fn&&, _Args&& ...) [with _Fn = Impresora::imprimir_RegInd(QWidget*, const std::vector<Data>&)::<lambda()>; _Args = {}; typename std::__invoke_result<typename std::decay<_Tp>::type, typename std::decay<_Args>::type ...>::type = void]', declared using local type 'Impresora::imprimir_RegInd(QWidget*, const std::vector<Data>&)::<lambda()>', is used but never defined [-fpermissive] 189 | async(launch __policy, _Fn&& __fn, _Args&&... __args); | ^~~~~ make.exe[2]: *** [build/Debug/MinGW-Windows/Impresora.o] Error 1
-
@jsulm actually i decided to pass all elements into the lambda
std::async(std::launch::async, [&] ( ) )
but for some reason it said its not compatible with my compiler, it said im using an incomplete function type
Im looking into Qt threats to see if i can do async workImpresora.cpp: In member function 'void Impresora::imprimir_RegInd(QWidget*, const std::vector<Data>&)': Impresora.cpp:98:6: error: invalid use of incomplete type 'class std::future<void>' 98 | }); | ^ In file included from Impresora.cpp:13: c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\future:125:11: note: declaration of 'class std::future<void>' 125 | class future; | ^~~~~~ c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\future: At global scope: c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\future:189:5: error: 'std::future<typename std::__invoke_result<typename std::decay<_Tp>::type, typename std::decay<_Args>::type ...>::type> std::async(std::launch, _Fn&&, _Args&& ...) [with _Fn = Impresora::imprimir_RegInd(QWidget*, const std::vector<Data>&)::<lambda()>; _Args = {}; typename std::__invoke_result<typename std::decay<_Tp>::type, typename std::decay<_Args>::type ...>::type = void]', declared using local type 'Impresora::imprimir_RegInd(QWidget*, const std::vector<Data>&)::<lambda()>', is used but never defined [-fpermissive] 189 | async(launch __policy, _Fn&& __fn, _Args&&... __args); | ^~~~~ make.exe[2]: *** [build/Debug/MinGW-Windows/Impresora.o] Error 1
@Lightshadown Did you include <future>
#include <future>
-
@Lightshadown Did you include <future>
#include <future>
@jsulm sorry to answer so late, but yes i did include the future header and yet it didnt work properly i had to optimice the data send to print and it worked better so no need for asinc at the moment