如何实现QProgressDialog?

时间:2018-02-12 10:30:11

标签: c++ qt qthread qprogressdialog

我尝试使用QProgressDialog向用户提供有关长任务进度的一些信息,同时允许他取消此任务。

基本上,我有QDialog个按钮Compute。点击它,我的QDialog父母的成员就会调用一个耗时的方法。此方法采用回调来告诉调用者工作进度。

问题是进度对话框在显示之前需要一些时间,并且没有立即考虑点击其Cancel按钮。

很明显我的代码中有一个小故障,但我不习惯Qt,我尝试了很多东西。我可能需要一个单独的线程。

我的代码摘录:

void MyDialog::callbackFunction(int value, void * objPtr) {
  ((QProgressDialog *)(objPtr))->setValue(value);
  QCoreApplication::processEvents();
}

void MyDialog::on_mComputeBtn_clicked()
{
   Compute();
}

void MyDialog::Compute()
{
  QProgressDialog progressDialog("Optimization in progress...", "Cancel", 0, 100, this);
  progressDialog.setMinimumDuration(500); // 500 ms
  progressDialog.setWindowModality(Qt::WindowModal);
  progressDialog.setValue(0);
  connect(&progressDialog, SIGNAL(canceled()), this, SLOT(Cancel()));
  QCoreApplication::processEvents();

    parentMember->LongComputation(callbackFunction);

    // probably useless
  progressDialog.reset();
  progressDialog.hide();
  QCoreApplication::processEvents();
}

2 个答案:

答案 0 :(得分:3)

由于您将最短持续时间设置为500毫秒,因此对话框不会立即显示。将其设置为0可使对话框立即显示进度更改或手动调用其显示功能。

为了使取消按钮工作,将长计算移动到另一个线程(例如使用QThread或std :: async)并让主事件循环继续执行。

实际上你的代码存在很多问题,但这两点应该指向正确的方向。根据我的经验,每次手动调用processEvents都会产生很大的代码味道。

答案 1 :(得分:1)

你所做的是尝试使用QProgressdialog的模态范例,不要让主事件泵发射,你也设置0.5秒超时,最小持续时间将确保暂停。也许无模式变体更适合你的情况。

如果进程有不连续的步骤,你可以在没有单独的线程

的情况下完成
class MyTask : public QObject
{
    Q_OBJECT
public:
    explicit MyTask(QObject *parent = 0);

signals:

public slots:
    void perform();
    void cancel();
private:
    int steps;
    QProgressDialog *pd;
    QTimer *t;

};

...

void MyDialog::on_mComputeBtn_clicked()
{
    myTask = new MyTask;
}
...


MyTask::MyTask(QObject *parent) :
    QObject(parent), steps(0)
{
    pd = new QProgressDialog("Task in progress.", "Cancel", 0, 100000);
    connect(pd, SIGNAL(canceled()), this, SLOT(cancel()));
    t = new QTimer(this);
    connect(t, SIGNAL(timeout()), this, SLOT(perform()));
    t->start(0);
}

void MyTask::perform()
{
    pd->setValue(steps);
    //... perform one percent of the operation
    steps++;
    if (steps > pd->maximum())
        t->stop();
}

void MyTask::cancel()
{
    t->stop();
    //... cleanup
}

QThread示例存在于此处:Qt 5 : update QProgressBar during QThread work via signal