views:

224

answers:

2

I'd like to know when my application is idle so that I can preload some content. Is there an event or something similar implemented in PyQt?

(I could also do it with threads, but this feels like being too complicated.)

+1  A: 

Have a look at QAbstractEventDispatcher. But ... I still suggest to use a thread. Reasons:

  1. It will be portable
  2. If you make a mistake in your code, the event loop will be broken -> You app might hang, exit all of a sudden, etc.
  3. While the preloading happens, your app hangs. No events will be processed unless you can preload the content one at a time, they are all very small, loading takes only a few milliseconds, etc.

Use a thread and send a signal to the main thread when the content is ready. It's so much more simple.

Aaron Digulla
+3  A: 

You have at least two different options, you can use a thread or use a timer. Qt's QThread class provides a priority property that you can set to make it only process when no other threads are running, which includes the GUI thread. The other option is a single shot timer. A QTimer with a timeout of 0 milliseconds puts an event on the back of the event queue so that all events and synchronous functions already active or scheduled will be processed first.

In code, the two options would look like the following:

// (1) use idle thread processing
MyQThreadSubclass idleThread;
idleThread.run(QThread::IdlePriority);

// (2) use QTimer::singleShot
QTimer::singleShot(0, receiver, SLOT(doIdleProcessingChunk));

If you go with the single shot QTimer, be careful how much processing you do as you can still block the Gui. You'd likely want to break it into chunks so that GUI won't start to lag:

// slot
void doIdleProcessingChunk() {
    /* ... main processing here ... */
    if (chunksRemain())
        QTimer::singleShot(0, receiver, SLOT(doIdleProcessingChunk));
}

Obviously, the above is C++ syntax, but to answer with respect to PyQt, use the single shot timer. In Python, the global interpreter lock is basically going to render much of your concurrency pointless if the implementation being called is performed within Python.

You also then have the choice of using Python threads or Qt threads, both are good for different reasons.

Kaleb Pederson
The second to last paragraph is very important. Make sure you understand the effect of the global interpreter lock before using threads in PyQt. QThreads *are* affected by that lock.
quark