Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

messageBox not shown correctly



  • Hi guys, my case is

    1. pop up a message box showing "waiting ..." and return the control back to the main loop.
    2. fire a worker thread to do the heavy job.
    3. monitor the worker thread, close the message box once the job is done and the worker thread is returned.
    4. if the Cancel button on the message box is clicked or the message box is closed while the job is still running, terminate the worker thread.

    My implementation is as follows:

    In my main window class constructor:

    m_waitReplyMsgBox = new QMessageBox(QMessageBox::Information, tr("Title"),
                                            "Waiting ...", QMessageBox::Cancel, this); // not show yet
    // not matter click x or Cancel buttion, call the slot to try to terminate the worker thread
    connect(m_waitReplyMsgBox, SIGNAL(finished(int)), this, SLOT(waitReplyCancelled()));
    m_waitReplyMsgBox->setModal(true);
    
    // for monitor the worker thread i used thread watcher.
    // Once the worker thread is returned, calling receivedReply() to close the message box
    connect(&m_waitReplyThreadWatcher, SIGNAL(finished()), this, SLOT(receivedReply()));
    

    When the job is to be activated (in my case, when double click the screen):

    m_waitReplyCancelled = false;
    m_waitReplyMsgBox->show(); // shows the message box and return immediately
    
     // fire a worker thread and the job is to be done in waitReply()
    QFuture<bool> future = QtConcurrent::run(this, &MainWindow::waitReply);
    m_waitReplyThreadWatcher.setFuture(future); // monitor the thread
    
    // member function to do the job
    bool MainWindow::waitReply() {
        bool received_valid_reply = false;
        while (!m_waitReplyCancelled) {
               if (Something Is Received)  {
                    received_valid_reply = true;
                    return received_valid_reply;
               }
        }
        return received_valid_reply;
    }
    
    // when the job in worker thread is done, close the message box
    void MainWindow::receivedReply() {
        if(m_waitReplyThreadWatcher.future().result()) {
            // do something with the results and close the message box
            m_waitReplyMsgBox->close(); // close the message box
        }
    }
    

    If the Cancel button is clicked or message box is closed by user during processing, terminate the worker thread by exiting the while loop.

    void MainWindow::waitReplyCancelled() {
        m_waitReplyCancelled = true;
    }
    

    This solution works half of the times and another half of the times, the message box just pops out without showing any content and also not closes by itself even the worker thread is returned normally. It's just hanging there until I manually click the x to close it. I have no idea but suspect it might be because the message box pops out (->show()) and closes (->close()) too soon (if the "heavy" job is done very fast), and the process event just got some problem to process them.

    Any idea on this? Thanks.



  • H, if you don't set the modal boolean, for example by commenting out:

    // m_waitReplyMsgBox->setModal(true);
    

    do you still get the same behavior?



  • hi @hskoglund I still get the same behavior and plus sometimes the message box only shows the title area. I set the modal because i want to block the operations when the message box is showing. Thanks.



  • Hi guys
    I solved this problem by adding a sleeping time duration in my worker thread preventing it from returning too quick. Then the message box gets shown properly and closed properly.

    // member function to do the job
    bool MainWindow::waitReply() {
        // Here to sleep for a while
        QThread::sleep(2);    
    
        bool received_valid_reply = false;
        while (!m_waitReplyCancelled) {
               if (Something Is Received)  {
                    received_valid_reply = true;
                    return received_valid_reply;
               }
        }
        return received_valid_reply;
    }