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. Async and QPainter, printing function

Async and QPainter, printing function

Scheduled Pinned Locked Moved Unsolved General and Desktop
8 Posts 4 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.
  • L Offline
    L Offline
    Lightshadown
    wrote on last edited by
    #1

    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 seconds

    Imp_RegIndiv_Boletas its where all the printing happends using qpainter, it expects 3 parameters Qpainter, Vector and Number of pages

    void 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);
            }
    }
    
    jeremy_kJ 1 Reply Last reply
    0
    • L Lightshadown

      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 seconds

      Imp_RegIndiv_Boletas its where all the printing happends using qpainter, it expects 3 parameters Qpainter, Vector and Number of pages

      void 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);
              }
      }
      
      jeremy_kJ Offline
      jeremy_kJ Offline
      jeremy_k
      wrote on last edited by
      #2

      @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 seconds

      Imp_RegIndiv_Boletas its where all the printing happends using qpainter, it expects 3 parameters Qpainter, Vector and Number of pages

      void 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.

      Asking a question about code? http://eel.is/iso-c++/testcase/

      L 1 Reply Last reply
      2
      • E Offline
        E Offline
        Ewan Green
        wrote on last edited by
        #3

        Qt has its own multithreading API.
        https://doc.qt.io/qt-5/qthread.html

        Ewan Green

        1 Reply Last reply
        0
        • jeremy_kJ jeremy_k

          @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 seconds

          Imp_RegIndiv_Boletas its where all the printing happends using qpainter, it expects 3 parameters Qpainter, Vector and Number of pages

          void 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.

          L Offline
          L Offline
          Lightshadown
          wrote on last edited by Lightshadown
          #4

          @jeremy_k

          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 function

          Impresora.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 happends

          std::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);
                  }
              });
          
          jsulmJ 1 Reply Last reply
          0
          • L Lightshadown

            @jeremy_k

            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 function

            Impresora.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 happends

            std::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);
                    }
                });
            
            jsulmJ Online
            jsulmJ Online
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @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".

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

            L 1 Reply Last reply
            2
            • jsulmJ jsulm

              @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".

              L Offline
              L Offline
              Lightshadown
              wrote on last edited by Lightshadown
              #6

              @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 work

              Impresora.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
              
              jsulmJ 1 Reply Last reply
              0
              • L Lightshadown

                @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 work

                Impresora.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
                
                jsulmJ Online
                jsulmJ Online
                jsulm
                Lifetime Qt Champion
                wrote on last edited by
                #7

                @Lightshadown Did you include <future>

                #include <future>
                

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

                L 1 Reply Last reply
                1
                • jsulmJ jsulm

                  @Lightshadown Did you include <future>

                  #include <future>
                  
                  L Offline
                  L Offline
                  Lightshadown
                  wrote on last edited by
                  #8

                  @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

                  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