简体   繁体   中英

How to prevent GUI from hanging while allowing 2nd operation to be performed alongwith 1st operation in Qt

Here I am explaining my problem statement in detail and the efforts I have put so far

A) Problem Statement : During printing if 'Stop Printing' pushbutton is pressed, the printing should stop at that moment!

B) My Work :

1. StartPrinitng_Pressed :

 void MainWindow :: on_StartPrinitng_Pressed()

{QSqlquery studentList;
 studentList("SELECT Name, address FROM class  WHERE Roll No = some       variable")

   while(studentList.next())
   {       
      Name=studentList.value(0).toString();   
      address=studentList.value(1).toString();   

      QTimer:: singleShot(1000,this,SLOT(StopNow()));   //calling stopNow function

      if(StopPrintingNow==0)
      {  //**   I am printing the fetched data (in a string)  by setting GPIO    pins  HIGH      **//  }


    }
 }

2. StopPrinting_Pressed :

 void MainWindow::on_StopPrinting_Pressed()
  {StopPrintingNow=1;} 

3. StopNow Function Declaration :

 void MainWindow::StopNow() 
  {
   if(StopPrintingNow==1)
   {   //**  I have reset all serials ports; Break;   **// }
   else if(StopPrintingNow==0)
   { QTimer::singleShot(1000,this,SLOT(on_startPrinting_pressed())); }
  }

C) Flow of program execution : As and when "StartPrinting" pushbutton is pressed, the query shown in my question executes which fetches data from database and perform simultaneous printing.

D) Problem Faced -

1.GUI is getting hanged while printing, hence StopPrinting button doesn't respond.

  1. Qtimer is not calling "StopNow function " while printing (though I have called it at correct position) enter image description here

Handling of timers and button presses is both covered by the Qt event loop -- which is blocked while you are looping over that SQL query. You have two options:

1) Periodically dispatch events in your while loop. This is as simple as

qApp->processEvents();

But you have to be careful, however: any events you trigger due to user interaction (or a timer) will block and your while loop will not run until the event is finished. In your case especially, you could end up running a second copy of your on_StartPrinitng_Pressed function.

2) Do the printing on a separate thread. This involves some more code, but the gist of it is that you create a SqlPrinter object with a startPrinting slot and stopPrinting slot. You then create a QThread and change its owner thread to that thread. Slot invocations will happen across the thread boundary and all will be fine.

class SqlPrinter : public QObject {
    Q_OBJECT
    public:
    SqlPrinter(QObject* parent = nullptr) : QObject(parent) {}
    public slots:
    void startPrinting();
    void stopPrinting();
};

In your main code, then do something like this, assuming that you have the two buttons named MainWindow_StartButton and MainWindow_StopButton :

QThread* printerThread = new QThread(qApp);
SqlPrinter* printer = new SqlPrinter;
printer->moveToThread(printerThread);
printerThread->start();
QObject::connect(MainWindow_StartButton, &QPushButton::clicked, printer, &SqlPrinter::StartPrinting);
QObject::connect(MainWindow_StopButton, &QPushButton::clicked, printer, &SqlPrinter::StopPrinting);

Don't forget to clean up SqlPrinter afterwards!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM