2016-10-10 5 views
0

私は簡単なUIを持つQtアプリを1つ持っています。QtでUIの変更が瞬時に行われないのはなぜですか?

ボタンをクリックすると、ボタンのスタイルが無効に設定され、バックグラウンドスレッドが開始されます。

void MyApp::buttonClicked() 
{ 
    theOnlyButton->setDisabled(true); 

    QThread *workerThread; 
    UploadWorker *worker; 

    if (uploadInProgress) { 
     QMessageBox::critical(this, "Error", "Another upload is already running!"); 
     return; 
    } 

    workerThread = new QThread; 

    worker  = new UploadWorker(QString("filename")); 

    worker->moveToThread(workerThread); 

    connect(workerThread, SIGNAL(started()), worker, SLOT(doWork())); 
    connect(worker, SIGNAL(finished(QString, QString)), workerThread, SLOT(quit())); 
    connect(worker, SIGNAL(finished(QString, QString)), worker, SLOT(deleteLater())); 
    // this takes care automatically of freeing memory 
    connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); 
    connect(worker, SIGNAL(finished(QString, QString)), this, SLOT(onUploadFinished(QString, QString))); 

    workerThread->start(); 

    uploadInProgress = true; 

} 

機能の詳細については、私の質問には無関係である - 私はすべての行にブレークポイントを設定し、ボタンが無効になったときにメインウィンドウを監視します。興味深いことに、それはtheOnlyButton->setDisabled(true);コールの後には発生しません。次の数行でも発生しません。実際には機能が最初に終了し、その後は無効として表示されます。その結果、ボタンは即座に無効にならないように見えますが、1秒未満になります。どうして?この瞬間を作る方法?

+0

"機能の詳細は私の質問とは関係ありません..."なぜそれらを含めるのですか?コードを[MCVE](http://stackoverflow.com/help/mcve)に編集します。 – MrEricSir

+0

*ボタンは即座に無効にされているようではなく、むしろ1秒未満になります。それから、あなたの機能には遅い操作があります。コードスニペットの関数は、終了するのに数ミリ秒以上かかるようには見えません。だから人間の目にはかなり瞬時に見えるはずです。 – thuga

+0

'UploadWorker'のコンストラクタは、時間がかかる何かをする可能性があり、' moveToThread'を呼び出す前にコンストラクタが実行されるときにGUIスレッドを停止させます。その場合、そのコードをワーカースレッドで実行される 'init'関数に移すことができます。 –

答えて

2

GUIスレッドから呼び出されたスロットにいるとき、GUIスレッドは他のことを行うことができません。イベントループに戻ったり、UIを再描画したり

QCoreApplication::processEvents()を呼び出すことでこれを回避することができますが、Right Thing To Do™は1つの単純なタスクに集中し、それらからすばやく戻ることです。

+0

新しいスレッドを開始するより簡単にすることはできません。これには、渡された引数の準備が含まれます。しかし、あなたの答えをありがとう、それは多くを説明します –

+0

デバッガで侵入しない限り、ボタンは、スロットを離れるとすぐに無効に設定する必要があります。 – krzaq

+1

@TomášNavara:スレッドを開始する前にボタンを無効にする必要がある場合。 'UploadWorker'を作成する場合、ボタンの無効化が目に見えるほど遅くなりすぎて、スロットを無効にしてから、' QMetaObject :: invokeMethod() 'またはシングルショット' QTimer'を使って別のスロットを呼び出しさせます。スレッドとワーカーを開始します。 –

1

この方法を試しましたか?スロットは、接続された順に実行されます。だから、

connect(theOnlyButton, &QPushButton::clicked, [&]() {theOnlyButton->setEnabled(false); }); // disable the button first 
connect(theOnlyButton, SIGNAL(clicked()), this, SLOT(buttonClicked()); 
+0

良いアイデア、ありがとう –

関連する問題