C++ 异步显示Qt对话框
我想在调用show()后立即显示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
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
,因为它会在应用程序中产生各种问题。将繁重的处理任务移动到不同的线程,这样就不会再阻塞主事件循环。