在按下按钮后我的Qt应用程序中我想隐藏该按钮并启动相当长的过程。当此进程正在运行时PushButton
不应该是可见的,但似乎正在等待正在执行的进程以及该隐藏按钮之后。在QWidget
插槽功能结束后看起来PushButton
正在刷新。这是我的简化代码:
void MainWindow::on_pushButton_clicked()
{
ui->progressBar->setVisible(true);
ui->pushButton->setVisible(false);
while(x<1000000) x++; //e.g of my long time function
}
当该功能(on_pushButton_clicked()
- >生成由鼠标 - >转到插槽)结束时,我的“视图”会更新并且按钮会消失。
是否有任何功能来刷新我的小部件或者我忘记了某事?
提前致谢
答案 0 :(得分:3)
在程序有机会重绘之前,不会显示对gui的更改,直到您返回为止。
你需要以某种方式推迟代码的执行:
void MainWindow::on_pushButton_clicked()
{
ui->progressBar->setVisible(true);
ui->pushButton->setVisible(false);
QMetaObject::invokeMethod(this, &MainWindow::longFunction, Qt::QueuedConnection);
}
void MainWindow::longFunction()
{
while(x<1000000) x++; //e.g of my long time function
}
这将返回到事件循环,然后运行longFunction,但它仍然会阻塞,进度条在完成之前不会显示任何更新。
要解决此问题,您需要将执行移至新线程或将功能拆分为较短的部分,然后依次使用QMetaObject::invokeMethod
和QueuedConnection
调用它们。
答案 1 :(得分:2)
为了使按钮改变状态,它需要返回到事件循环中的处理事件。
你可以在while循环之前调用QApplication::processEvents来解决这个问题,尽管在启动长时间函数之前,通过调用QueuedConnection函数最好自然地返回事件循环
或者,更好的方法是在单独的线程中运行该函数,这将使您的GUI在处理“长函数”期间保持活动状态
首先创建一个对象来封装将要完成工作的函数: -
class Worker : public QObject {
Q_OBJECT
public:
Worker();
~Worker();
public slots:
void process(); // This is where your long function will process
signals:
void finished();
void error(QString err);
};
void Worker::process()
{
while(x<1000000) x++; //e.g of my long time function
emit finished();
}
创建新线程并在单击按钮时启动它
void MainWindow::on_pushButton_clicked()
{
// change button visibility
ui->progressBar->setVisible(true);
ui->pushButton->setVisible(false);
// create the new thread and start the long function
QThread* thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
connect(thread, SIGNAL(started()), worker, SLOT(process()));
//ensure the objects are cleared up when the work is done
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
//start the thread and the long function processing
thread->start();
}