Modal QProgressDialog从工作线程更新

时间:2018-04-04 08:29:35

标签: c++ qt qthread qprogressdialog

我想从我的工作线程更新模态 QProgressDialog。但是,如果我将对话框设置为模态,我的应用程序崩溃(并且对话框没有显示任何进度)。如果我不这样做,一切都很顺利(但是用户可以修改程序的其余部分,这可能会导致问题)。

我做错了什么?

最小代码示例如下:

$this_category->parent

2 个答案:

答案 0 :(得分:1)

你的线程毫无意义。它没有任何实际意义。您也可以在QApplication::processEvents方法中调用read_file。但你不应该,调用processEvents是不好的做法。

您应该删除while循环,并使您的进度对话框成为您班级的成员。我真的不喜欢那个lambda看起来如何。我个人只会使用filereader::read_file作为插槽。

请注意Qt::windowModal阻止输入父窗口。您的进度对话框没有父级。因此,您必须致电progress->setModal(true)progress.setWindowModality(Qt::ApplicationModal);。或者设置父级。

这是一个小例子(它不是为您的应用程序量身定制的,但它应该指向正确的方向):

#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"

答案 1 :(得分:0)

首先,如果您希望进度为Modal,为什么需要在后台线程中执行文件读取?您可以在主(GUI)线程中执行文件读取操作,只要您不时检查取消状态。