0

I'm writing a program that enables the WLAN drivers on a device, and then searches for local Wi-Fi connections. Turning on the drivers and performing the scan are done using the command line with QProcess. This all works fine; the problem is that I try to update the UI before the scan happens, to let the user know what is happening. Here's the code:

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();

Simply put, the user presses a button to start the scan, and I want the button to change text to say "Searching, please wait..." before the scan starts, since it takes a few seconds for the scan to finish.

However, the UI doesn't update before the scan starts. The system simply appears locked up for a few seconds, then moves on to the rest of the program (which brings up a separate window with the Wi-Fi info). I tried getting the thread to sleep for a few seconds between the button text change and the scan, but the result is the same. Is there a reason that the text won't update before the scan begins, even though the scan is after the setText command in the code?

If it helps, I'm running Qt 4.8.4 in Qt Creator using Ubuntu.

Churchbus
  • 53
  • 5

2 Answers2

4

The UI is blocked because you call waitForFinished() on it in the UI thread. To avoid that you can either:

  1. Don't call waitForFinished(), but connect to the finished() and error() signals of QProcess instead. For that, you need to make QProcess a class member so that the instance survives when Qt returns to the event loop. That'd be the "normal way to do it.

  2. Move the whole QProcess instantiation and execution into another thread. This is slightly more complex and probably only worth the effort if you have a more complicated control flow involving multiple processes that depend on each other.

Frank Osterfeld
  • 24,815
  • 5
  • 58
  • 70
  • It makes sense that waitForFinished() blocks the UI, but what I don't understand is why it blocks the UI before the previous code has executed. Does it have to do with the way Qt handles UI updates? I've only been using Qt for a few weeks, so I'm not too keen on some of the finer details. – Churchbus Apr 15 '15 at 15:31
  • @Churchbus The GUI is updated when your main thread goes back to the event loop. GUI updates are events. Events are described pretty well in the [docs](http://doc.qt.io/qt-4.8/eventsandfilters.html). You should also avoid using `QApplication::processEvents`. Instead do what Frank suggested in this answer. – thuga Apr 16 '15 at 06:57
0

This is by no means an ideal solution. However, a call to QApplication::processEvents() should do the trick:

ui->toolButton->setText("Searching, please wait...");
QApplication::processEvents();
Nicholas Betsworth
  • 1,707
  • 19
  • 24
  • Thanks, that worked! I had tried doing something similar with ui->toolButton->update(), but it didn't have any effect. I'll try to find a more robust solution, but this will work in the meantime. – Churchbus Apr 15 '15 at 15:26