[英]Modal QProgressDialog updated from worker thread
我想從我的工作線程更新模態 QProgressDialog。 但是,如果將對話框設置為模式對話框,則我的應用程序將崩潰(對話框未顯示任何進度)。 如果我不這樣做,一切都會很好(但是用戶可以修改程序的其余部分,這可能會導致問題)。
我究竟做錯了什么?
最小代碼示例如下:
filereader qfr;
QProgressDialog progress("Importing file.", "Cancel", 0, file_size);
connect(&qfr, &filereader::signalProgress, &progress, &QProgressDialog::setValue, Qt::QueuedConnection);
QThread worker_thread;
std::atomic<bool> success = false;
connect(&worker_thread, &QThread::started,
[&]() {
success = qfr.read_file(/* parameters */);
worker_thread.quit();});
worker_thread.start();
//progress.setWindowModality(Qt::WindowModal); // Works only fine when this line is commented !!
while (worker_thread.isRunning()) {
QApplication::processEvents();
QThread::sleep(0);
}
progress.close();
您的線程幾乎毫無意義。 它沒有真正的目的。 您也可以在read_file
方法中調用QApplication::processEvents
。 但是您不應該,調用processEvents
是不好的做法。
您應該做的是刪除while
循環,並使進度對話框成為您班級的成員。 我也不很喜歡那個lambda的樣子。 我個人只是將filereader::read_file
用作插槽。
注意, Qt::windowModal
阻止輸入到父窗口。 您的進度對話框沒有父級。 因此,您必須調用progress->setModal(true)
或progress.setWindowModality(Qt::ApplicationModal);
progress->setModal(true)
。 或為其設置父項。
這是一個小示例(它不是為您的應用程序量身定制的,但應為您指明正確的方向):
#include <QtWidgets>
class Worker : public QObject
{
Q_OBJECT
public:
Worker(QObject *parent = nullptr) : QObject(parent){}
public slots:
void simulateLongProcess()
{
for(int i = 0; i < 101; i++)
{
emit progressChanged(i);
QThread::msleep(100);
}
emit finishedWorking(true);
}
signals:
void progressChanged(int progress);
void finishedWorking(bool result);
};
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr) : QWidget(parent)
{
setLayout(new QHBoxLayout);
progress_dialog.setModal(true);
progress_dialog.setAutoReset(false);
progress_dialog.setCancelButton(nullptr);
QThread *thread = new QThread(this);
connect(thread, &QThread::started, &worker, &Worker::simulateLongProcess);
connect(&worker, &Worker::finishedWorking, thread, &QThread::quit);
connect(&worker, &Worker::progressChanged, &progress_dialog, &QProgressDialog::setValue);
connect(&worker, &Worker::finishedWorking, &progress_dialog, &QProgressDialog::close);
connect(&worker, &Worker::finishedWorking, this, &Widget::handleResult);
QPushButton * start_button = new QPushButton("START");
connect(start_button, &QPushButton::clicked, this, [=]
{
progress_dialog.show();
thread->start();
});
layout()->addWidget(start_button);
resize(400, 300);
}
public slots:
void handleResult(bool result)
{
// do something with the result
}
private:
QProgressDialog progress_dialog;
Worker worker;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
首先,如果您希望進度為Modal,為什么需要在后台線程中執行文件讀取? 您可以在主(GUI)線程中執行文件讀取操作,只要您不時檢查取消狀態即可。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.