Qt小部件元素不想隐藏

时间:2014-08-28 08:53:23

标签: qt user-interface refresh

在按下按钮后我的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() - >生成由鼠标 - >转到插槽)结束时,我的“视图”会更新并且按钮会消失。 是否有任何功能来刷新我的小部件或者我忘记了某事?

提前致谢

2 个答案:

答案 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::invokeMethodQueuedConnection调用它们。

答案 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();          
}