Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 异步显示Qt对话框_C++_Qt_C++11 - Fatal编程技术网

C++ 异步显示Qt对话框

C++ 异步显示Qt对话框,c++,qt,c++11,C++,Qt,C++11,我想在调用show()后立即显示QT对话框;无需等待函数结束 void SomeFunction() { dialog_.reset(new MessageBoxProgression(this, SLOT(cancel())); dialog_->show();// not displayed waits for longOperation() to finish longOperation(); } dialog_uu有一个进度条,需要异步显示和更新,但当前,dialog_uuu在l

我想在调用show()后立即显示QT对话框;无需等待函数结束

void SomeFunction()
{
dialog_.reset(new MessageBoxProgression(this, SLOT(cancel()));
dialog_->show();// not displayed waits for longOperation() to finish
longOperation();
}
dialog_uu有一个进度条,需要异步显示和更新,但当前,dialog_uuu在longOperation()完成执行后才会显示

编辑:可以这样做吗?

void SomeFunction()
{
dialog_.reset(new MessageBoxProgression(this, SLOT(cancel()));
dialog_->show();// not displayed waits for longOperation() to finish

QApplication::processEvents();
longOperation();

update(dialog_);
QApplication::processEvents();

longOperation2();
}

只需添加QApplication::processEvents()


这将解决问题

只需添加QApplication::processEvents()


这将解决问题

主线程除了gui工作之外不应该做任何事情。长时间运行的操作根本不属于主线程。如果您有一个长时间运行的操作,您应该异步执行它

我们可以找出一些常见的长时间运行特性:

class LongOperationBase : public QObject {
  Q_OBJECT
  std::atomic_bool stop, running;
protected:
  bool shouldRun() const { return !stop; }
  virtual void compute() = 0;
public:
  Q_SLOT void start() {
    stop = false;
    emit started();
    QtConcurrent::run([this]{
      if (running || stop) return;
      running = true;
      compute();
      running = false;
    });
  }
  LongOperationBase() {}
  LongOperationBase(QProgressDialog *pd) {
    connectTo(pd);
  }
  bool isRunning() const { return running; }
  Q_SLOT void cancel() { stop = true; } // thread-safe
  Q_SIGNAL void started();
  Q_SIGNAL void hasRange(int);
  Q_SIGNAL void hasProgress(int);
  void connectTo(QProgressDialog *pd) {
    using B = LongOperationBase;
    connect(this, &B::started, pd, &QProgressDialog::show);
    connect(this, &B::hasRange, pd, &QProgressDialog::setMaximum);
    connect(this, &B::hasProgress, pd, &QProgressDialog::setValue);
    connect(pd, &QProgressDialog::canceled, this, &B::cancel, Qt::DirectConnection);
  }
};
假设您有以下长操作-输入和输出数据类型仅作为示例给出。每个循环迭代应该花费1-10毫秒,以最小化检查状态和发出进度的开销。您可以很容易地每隔
M次
迭代执行这些检查

struct LongOperation final : LongOperationBase {
  std::vector<int> input;
  std::vector<double> output;
  using LongOperationBase::LongOperationBase;
  void compute() override {
    size_t const N = input.size();
    size_t const M = 1;
    emit hasRange(N);
    for (size_t i = 0, j = 0; i < N; ++i, ++j) {
      // operate on input, generate output
      ...
      if (j == (M-1)) {
        emit hasProgress(i);
        if (!shouldRun()) break;
        j = 0;
      }
    }
  }
};

中给出了使用
QFuture
系统的替代方法,但该方法不足以简化进度指示。上述基于QObject的方法在过渡期间是可行的。

主线程不应该做gui工作之外的任何事情。长时间运行的操作根本不属于主线程。如果您有一个长时间运行的操作,您应该异步执行它

我们可以找出一些常见的长时间运行特性:

class LongOperationBase : public QObject {
  Q_OBJECT
  std::atomic_bool stop, running;
protected:
  bool shouldRun() const { return !stop; }
  virtual void compute() = 0;
public:
  Q_SLOT void start() {
    stop = false;
    emit started();
    QtConcurrent::run([this]{
      if (running || stop) return;
      running = true;
      compute();
      running = false;
    });
  }
  LongOperationBase() {}
  LongOperationBase(QProgressDialog *pd) {
    connectTo(pd);
  }
  bool isRunning() const { return running; }
  Q_SLOT void cancel() { stop = true; } // thread-safe
  Q_SIGNAL void started();
  Q_SIGNAL void hasRange(int);
  Q_SIGNAL void hasProgress(int);
  void connectTo(QProgressDialog *pd) {
    using B = LongOperationBase;
    connect(this, &B::started, pd, &QProgressDialog::show);
    connect(this, &B::hasRange, pd, &QProgressDialog::setMaximum);
    connect(this, &B::hasProgress, pd, &QProgressDialog::setValue);
    connect(pd, &QProgressDialog::canceled, this, &B::cancel, Qt::DirectConnection);
  }
};
假设您有以下长操作-输入和输出数据类型仅作为示例给出。每个循环迭代应该花费1-10毫秒,以最小化检查状态和发出进度的开销。您可以很容易地每隔
M次
迭代执行这些检查

struct LongOperation final : LongOperationBase {
  std::vector<int> input;
  std::vector<double> output;
  using LongOperationBase::LongOperationBase;
  void compute() override {
    size_t const N = input.size();
    size_t const M = 1;
    emit hasRange(N);
    for (size_t i = 0, j = 0; i < N; ++i, ++j) {
      // operate on input, generate output
      ...
      if (j == (M-1)) {
        emit hasProgress(i);
        if (!shouldRun()) break;
        j = 0;
      }
    }
  }
};

中给出了使用
QFuture
系统的替代方法,但该方法不足以简化进度指示。上述基于
QObject
的方法是一个可行的解决方案。

使用:
qApp->processEvents()或在另一个线程中运行
longOperation()
,第二个线程是最合适的,通常可能是代码中没有任何问题的副本,您可以将长操作移动到其他线程
QApplication::processEvents
是一个可怕的想法,应该避免或在另一个线程中运行
longOperation()
,第二个线程是最合适的,通常可能是代码中没有任何问题的副本,您可以将长操作移动到其他线程
QApplication::processEvents
是一个可怕的想法,应该避免。dialog无响应,dialog内的按钮不会单击。@SatyamRaikar如果不使用QApplication::processEvents()是否有响应?@SatyamRaikar由于事件循环被阻止,它们不会单击
QApplication::processEvents
将告诉它在调用时只处理一次事件。无论如何,您都应该避免使用
processEvents
,因为它会在应用程序中产生各种问题。将繁重的处理任务移动到不同的线程,这样您就不会再阻止主事件循环。对话框没有响应,对话框内的按钮不会单击。@SatyamRaikar如果不使用QApplication::processEvents()是否有响应?@SatyamRaikar由于事件循环被阻止,它们不会单击
QApplication::processEvents
将告诉它在调用时只处理一次事件。无论如何,您都应该避免使用
processEvents
,因为它会在应用程序中产生各种问题。将繁重的处理任务移动到不同的线程,这样就不会再阻塞主事件循环。