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

QProgressDialog dont show Bar or Dialog is shown to late



  • Me again. I have a Problem i cant solve by my self. Its not clear for me whats wrong. i also tried to put the Code in a QThread, but nothing works.

    The only Thing i want is a QProgressDialog. I have a Variable with Attachments and in these Attachments are Filepathes. I want to copy files and close the Form.

    But the Problem is with my Code, that it only shows the Dialog Window, but not the Progressbar. For less then 1 second i can see 100% is poping and then the Form closes. Here is my Code.

    void DiaryWindow::on_pbSave_clicked()
    {
        QProgressDialog progress("Saving...", "", 0, mAttachments.count(), this);
        progress.setWindowModality(Qt::WindowModal);
        progress.setCancelButton(0);
        progress.setValue(0);
        progress.show();
    
        for (int i = 0; i <= mAttachments.count(); i++)
        {
            if (i < mAttachments.count())
            {
                QString oldPath = mAttachments.at(i).absoluteFilePath();
                QString newPath = mAppDataLocation + QString(QDir::separator()) + mAttachments.at(i).fileName();
    
                while (QFile(newPath).exists())
                {
                    QString suffix = "." + QFileInfo(newPath).suffix();
                    newPath = QFileInfo(newPath).absolutePath() + QString(QDir::separator()) +
                            mAttachments.at(i).baseName() + QString::number(i) + suffix;
                }
    
                QFile(oldPath).copy(oldPath, newPath);
            }
            else
            {
                //Database Actions
            }
    
            progress.setValue(i);
        }
    
        progress.setValue(mAttachments.count());
    
        this->close();
    }
    

    Anyone has an Idea why my QProgressDialog isnt working correctly? I worked now for hourse on that and im really mad and tired.


  • Qt Champions 2019

    @Fuel You're blocking the Qt event loop with your nested loops. That means: as long as on_pbSave_clicked() is executed the event loop is blocked and cannot handle the UI events. That's why you don't see your progress dialog working correctly. As a work around (not very clean solution) you can call http://doc.qt.io/qt-5/qcoreapplication.html#processEvents inside your for-loop.

    QFile(oldPath).copy(oldPath, newPath);
    QApplication::processEvents();
    

    In general you should avoid blocking operations in Qt. If you have such long lasting operations move them to a thread. But don't update UI in that thread! This is not supported. Instead emit a signal in this thread each time you want to update UI (progress dialog in your case) and in the slot you then update UI.



  • Really much thanks for your Help. I understand what you mean, but i dont know how to do that. Can you please give me some Pseudo Code? Or a Link? Just to understand.

    I have know something like this

    void DiaryWindow::on_pbSave_clicked()
    {
        mThread = new QThread();
        mProgress = new QProgressDialog("Saving...", "", 0, mAttachments.count(), this);
        mProgress->setWindowModality(Qt::WindowModal);
        mProgress->setCancelButton(0);
        mProgress->setAttribute(Qt::WA_DeleteOnClose);
        mProgress->setValue(0);
        mProgress->show();
    
        connect(mThread, SIGNAL(started()), this, SLOT(saving()));
        connect(mThread, SIGNAL(finished()), mThread, SLOT(deleteLater()));
    
        mThread->start();
    
        if (mThread->isFinished())
            this->close();
    }
    
    void DiaryWindow::saving()
    {
        for (int i = 0; i <= mAttachments.count(); i++)
        {
            if (i < mAttachments.count())
            {
                QString oldPath = mAttachments.at(i).absoluteFilePath();
                QString newPath = mAppDataLocation + QString(QDir::separator()) + mAttachments.at(i).fileName();
    
                while (QFile(newPath).exists())
                {
                    QString suffix = "." + QFileInfo(newPath).suffix();
                    newPath = QFileInfo(newPath).absolutePath() + QString(QDir::separator()) +
                            mAttachments.at(i).baseName() + QString::number(i) + suffix;
                }
    
                QFile(oldPath).copy(oldPath, newPath);
            }
            else
            {
                //Database Actions
            }
    
            emit updateProgress(i);
        }
    }
    
    void DiaryWindow::updateProgress(int i)
    {
        mProgress->setValue(i);
    }
    

  • Qt Champions 2019

    @Fuel I already gave you the code. Add this line

    QApplication::processEvents();
    

    inside your for-loop.
    Or do you want to use a thread? In this case you should start here: http://doc.qt.io/qt-5/threads-technologies.html
    This

    if (mThread->isFinished())
            this->close();
    

    should be removed. Close when thread finished.
    In DiaryWindow::saving() you should emit a signal each time you copied a file. Connect a slot to this signal and in this slot update your progress dialog.



  • With

    QApplication::processEvents();
    

    it works. I tried to do that with QThread, but i failed. Maybe i try it later again. At the moment im happy that it works.



  • @Fuel

    There also is this function setMinimumDuration that claims to set the time that must pass before the dialog appears. Default setting is 4 seconds. http://doc.qt.io/qt-5.9/qprogressdialog.html#minimumDuration-prop

    -Michael.


  • Qt Champions 2019

    @Fuel Yes, this is quick&dirty solution.
    Using a thread is a bit more work, but cleaner.



  • I tried to do that now with QThread, but i dont success at all. Anyone has Example Code to show me how i do that? All Solutions i tried fails because of different Errors. I really dont have an Idea how to do that. Example Codes i found didnt help me. Please anyone has an good Example?

    First i cant use GUI in a Thread. Then i got Errors that i cant send Events to a Object in a different Thread. And so on. I really had much of strange Errors.


  • Qt Champions 2019

    @Fuel You should take a look at this: https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
    If you have any problems post your code, so others can help.


Log in to reply