0

1 つの関数が実行されているときにビジー待機バーを表示しようとしています。私の問題は、関数が開始されると動きが止まることです。

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 を 1 回だけ (1 つのファイルに対して) 呼び出すと正常に動作し、バーが移動しますが、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;

};
4

1 に答える 1

1

QtのUIはイベント駆動型です。したがって、uiと同じスレッドでコードを実行すると、関数が終了するまですべてのuiイベントがブロックされます。進捗状況を示すには2つのアプローチがあります。

  1. 計算にスレッドを使用し、更新イベントをUIに送信します
  2. より簡単な方法:それぞれの後に静的メソッドsetValueshow呼び出します。QApplication::processEvents();呼び出しQApplication::processEvents()は、イベントループで現在キューに入れられているイベントをディスパッチします。これらのイベントには、UI関連のすべてのイベントが含まれます

これがgcc/mingwgccのコードサンプルです

#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.25秒ごとに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;
于 2012-11-05T10:23:30.643 に答える