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.


  • Moderators

    @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);
    }
    

  • Moderators

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


  • Moderators

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


  • Moderators

    @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
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.