【问题标题】:QProcess preventing UI updatesQProcess 阻止 UI 更新
【发布时间】:2015-04-15 14:58:47
【问题描述】:

我正在编写一个程序来启用设备上的 WLAN 驱动程序,然后搜索本地 Wi-Fi 连接。使用带有 QProcess 的命令行来打开驱动程序并执行扫描。这一切都很好;问题是我尝试在扫描发生之前更新 UI,让用户知道发生了什么。代码如下:

ui->toolButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
ui->toolButton->setText("Searching, please wait...");

// Enable WLAN drivers
QProcess process;
process.start(turn on WLAN);
process.waitForFinished();

// Get WLAN information for available networks
process.start("iwlist wlan0 scan");   // Find wireless access points
process.waitForFinished();
QString wirelessInfo = process.readAll();

简单地说,用户按下按钮开始扫描,我希望按钮在扫描开始前将文本更改为“正在搜索,请稍候...”,因为扫描需要几秒钟完成。

但是,用户界面不会在扫描开始前更新。系统只是锁定了几秒钟,然后继续程序的其余部分(这会打开一个带有 Wi-Fi 信息的单独窗口)。我尝试在按钮文本更改和扫描之间让线程休眠几秒钟,但结果是一样的。是否存在文本在扫描开始之前不会更新的原因,即使扫描是在代码中的 setText 命令之后进行的?

如果有帮助,我正在使用 Ubuntu 在 Qt Creator 中运行 Qt 4.8.4。

【问题讨论】:

    标签: c++ qt qprocess


    【解决方案1】:

    UI 被阻塞,因为您在 UI 线程中对其调用 waitForFinished()。为避免这种情况,您可以:

    1. 不要调用waitForFinished(),而是连接到QProcess 的finished() 和error() 信号。为此,您需要使 QProcess 成为类成员,以便在 Qt 返回事件循环时实例仍然存在。那将是“正常的做法”。

    2. 将整个 QProcess 实例化和执行移到另一个线程中。这会稍微复杂一些,并且只有在您有一个涉及多个相互依赖的进程的更复杂的控制流时才值得付出努力。

    【讨论】:

    • waitForFinished() 阻塞 UI 是有道理的,但我不明白为什么它会在前面的代码执行之前阻塞 UI。它与 Qt 处理 UI 更新的方式有关吗?我只使用 Qt 几个星期,所以我不太热衷于一些更精细的细节。
    • @Churchbus 当您的主线程返回事件循环时,GUI 会更新。 GUI 更新是事件。 docs 中很好地描述了事件。您还应该避免使用QApplication::processEvents。而是按照弗兰克在此答案中的建议进行操作。
    【解决方案2】:

    这绝不是一个理想的解决方案。但是,调用 QApplication::processEvents() 应该可以解决问题:

    ui->toolButton->setText("Searching, please wait...");
    QApplication::processEvents();
    

    【讨论】:

    • 谢谢,成功了!我曾尝试用 ui->toolButton->update() 做类似的事情,但没有任何效果。我会尝试找到一个更强大的解决方案,但这会在此期间奏效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多