QProgresdialog:忙碌的等待栏在执行功能时没有移动

时间:2012-11-05 09:34:32

标签: c++ qt thread-safety progress-bar

我正在尝试在执行一个函数时显示忙碌的等待条,我的问题是它在函数启动后停止移动。

MyProgressDialog *progBar= new MyProgressDialog();
    QProgressBar* bar = new QProgressBar(progBar);
    bar->setRange(0, 0);
    bar->setValue(0);

    progBar->setBar(bar);
    QString labeltext=QString("<qt> <center><big><b>%1</b></big></center> <br><b>%2</b><br> %3 <br><b>%4</b><br> %5</qt>")
                         .arg(progBar->labeltext)
                         .arg("File in :")
                         .arg(FileI)
                         .arg("File out :")
                         .arg(FileO);
    progBar->label->setText(labeltext);    
    progBar->setValue(10);
    progBar->show();
    progBar->setValue(20);
    Sleep(500);
    progBar->setValue(50);
    Sleep(500);
    MyFunction(FileI,FileO,mode,key);
    Sleep(500);
    progBar->setValue(80);
    Sleep(500);
    progBar->setValue(100);
    progBar->close();
    delete bar;
    delete progBar;

我使用睡眠和设定值来改变我的功能以使其移动但是徒劳,当我移除它们时MyProgressdialog没有显示其内容,我是否需要在单独的线程中午餐?  我尝试使用QFutureWatcher:

 QFutureWatcher<void> futureWatcher;
                       QFuture<void> f1 = run(
                                              MyFunction,
                                              filePath,
                                              file.absolutePath()+"/OUT_"+fileN,
                                              1,
                                              key
                                              );
                       QObject::connect(&futureWatcher, SIGNAL(finished()), progBar, SLOT(reset()));
                       QObject::connect(progBar, SIGNAL(canceled()), &futureWatcher, SLOT(cancel()));
                       QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), progBar, SLOT(setRange(int,int)));
                       QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), progBar, SLOT(setValue(int)));

                       // Start the computation.
                       futureWatcher.setFuture(f1);
                       // Display the dialog and start the event loop.
                       progBar->exec();
                       futureWatcher.waitForFinished();
                       delete progBar;

当我只调用一次MyFunction(对于一个文件)时它工作正常并且我的栏正在移动但是当我多次调用MyFunction(对于许多文件连续)时出现问题:它可以工作但我得到相同的OUT_file对于所有处理过的文件,我认为这是多线程问题。

编辑: class MyProgressDialog

class MyProgressDialog: public QProgressDialog
{
  Q_OBJECT

  public:

    MyProgressDialog()
      {

      qDebug()<<"MyProgressDialog constructor";

      label=new QLabel(this);

      QPalette* palette = new QPalette();
      palette->setColor(QPalette::Window,"#F8F8FF");
      setPalette(*palette);

      QFont* font = new QFont("Courier New");
          font->setItalic(true);
          font->setPixelSize(15);
      setFont(*font);
      adjustSize();

     setWindowIcon(QIcon(QApplication::applicationDirPath()+"/icons/icon1.png"));
     setWindowFlags(Qt::WindowStaysOnTopHint);
     setMinimumWidth(500);
     setMinimumHeight(200);
     labeltext=QString("Please wait until Encryption/Decryption was done");
     label->setText(labeltext);
     label->adjustSize();
     label->setWordWrap (true);
     setLabel(label);

     setRange(0,100);
     setWindowTitle("MyFunction progress");        
     setModal(true);    

    }
    ~MyProgressDialog()
    {
        qDebug()<<"MyProgressDialog destructor";
        delete label;
    }



public:

  int value;     
  QString labeltext;
  QLabel* label;

};

1 个答案:

答案 0 :(得分:1)

Qt中的UI是事件驱动的。因此,在与ui相同的线程中执行代码将阻止每个ui事件,直到您的函数完成。有两种方法可以显示进展。

  1. 使用线程进行计算并将更新事件发送到UI
  2. 更简单的方法:在每次setValueshow调用后调用QApplication::processEvents();静态方法。调用QApplication::processEvents()将调度当前在事件循环中排队的事件。这些事件包括所有与ui相关的事件
  3. 以下是gcc / mingw gcc的代码示例

    #include <QApplication>
    #include <QProgressBar>
    
    int main(int argc, char * argv[])
    {
        QApplication app(argc, argv);
    
        QProgressBar bar;
        bar.setRange(0, 100);
        bar.show();
        app.processEvents();
        usleep(250000);
    
        for(int i = 1; i <= 10; ++i)
        {
                bar.setValue(i * 10);
                app.processEvents();
                usleep(250000);
        }
    
        return 0;
    }
    

    它显示进度条,并按0,05s步骤10步

    您的代码应如下所示:

    MyProgressDialog *progBar= new MyProgressDialog();
    QProgressBar* bar = new QProgressBar(progBar);
    bar->setRange(0, 100); // note your "busy state won't be shown as you're changing value right after show
    bar->setValue(0);
    
    progBar->setBar(bar);
    QString labeltext=QString("<qt> <center><big><b>%1</b></big></center> <br><b>%2</b><br> %3 <br><b>%4</b><br> %5</qt>")
                         .arg(progBar->labeltext)
                         .arg("File in :")
                         .arg(FileI)
                         .arg("File out :")
                         .arg(FileO);
    progBar->label->setText(labeltext);    
    progBar->setValue(10);
    progBar->show();
    QApplication::processEvents(); // HERE
    progBar->setValue(20);
    QApplication::processEvents(); // HERE
    Sleep(500);
    progBar->setValue(50);
    QApplication::processEvents(); // HERE
    Sleep(500);
    MyFunction(FileI,FileO,mode,key);
    Sleep(500);
    progBar->setValue(80);
    QApplication::processEvents(); // HERE
    Sleep(500);
    progBar->setValue(100);
    progBar->close();
    QApplication::processEvents(); // HERE
    delete bar;
    delete progBar;