我想在调用show()后立即显示QT对话框;无需等待功能结束。
void SomeFunction()
{
dialog_.reset(new MessageBoxProgression(this, SLOT(cancel()));
dialog_->show();// not displayed waits for longOperation() to finish
longOperation();
}
dialog_有一个进度条,需要异步显示和更新,但是目前,在longOperation()执行完毕之前,dialog_才会显示。
编辑:可以这样做吗?
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();
}
答案 0 :(得分:1)
只需添加QApplication :: processEvents();
void SomeFunction()
{
dialog_.reset(new MessageBoxProgression(this, SLOT(cancel()));
dialog_->show();// not displayed waits for longOperation() to finish
QApplication::processEvents();
longOperation();
}
这将解决问题
答案 1 :(得分:1)
除了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-10ms来最小化检查状态和发出进度的开销。您可以在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;
}
}
}
};
然后,以异步方式执行它:
class Window : public QWidget {
Q_OBJECT
QProgressDialog m_progress{this};
LongOperation m_operation{&m_progress};
...
public:
Window(QWidget * parent = {}) : QWidget(parent) {}
void runLongOperation() {
m_operation.start();
}
...
};
使用QFuture
系统的替代方法在this answer中给出,但它不够完整以简化进度指示。上述基于QObject
的方法在过渡期间是一个可行的解决方案。