Qt控件元素不想隐藏
问题描述:
在我的Qt应用程序按下按钮后,我想隐藏那个按钮并开始相当长的过程。当这个进程运行时,PushButton不应该是可见的,但它似乎在等待执行的进程以及隐藏按钮之后。看起来QWidget在按钮插槽功能结束后刷新。这是我的简化的代码:Qt控件元素不想隐藏
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 - 小鼠 - 通过产生>>去时隙)结束了我的“视图”被更新和按钮dissappear。 是否有任何功能来刷新我的小部件或maby我忘了什么?
在此先感谢
答
为了使按钮更改状态,它需要返回到事件循环中的处理事件。
为了解决这个问题,你可以在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();
}
答
变化到GUI AR时直到程序有机会重绘本身,直到你回来才会发生。
你需要以某种方式推迟代码的执行:
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
调用它们。
创建一个全新的类,所有的锅炉都是矫枉过正的。将长期运行的代码分离成一个私有函数并获得'QtConcurrent'来完成所有线程设置和执行会更好。 – RobbieE 2014-08-29 05:53:17
@RobbieE是的,这是很多代码,但我会避免QtConcurrent:http://comments.gmane.org/gmane.comp.lib.qt.devel/7942 – TheDarkKnight 2014-08-29 07:42:26