Re: [PyQt] Processing signals from a called method while the method executes

2010-07-02 Thread alanm
On Friday 02 July 2010 12:03:29 pm Jan Haag wrote:
> On 7/2/10 3:38 PM, alanm wrote:
> > On Friday 02 July 2010 1:17:06 am Andreas Pakulat wrote:
> >> Don't block the event-loop with your processor. The signals are
> >> delivered as you expect, but the widget is not redrawn with that
> >> message. The reason is that your processing blocks the Qt event loop and
> >> hence no painting is done.
> >> 
> >> Possible options to not block the event loop that long would be to use a
> >> QTimer to schedule each part of your processing after the next
> >> event-loop run. The other option would be moving the processing into a
> >> separate thread, you should only go this route after making familiar
> >> with multi-threading though.
> >> 
> >> Andreas
> > 
> > Thanks for the reply.  I don't think I understand, though.  I read in the
> > QTimer documentation where I can do a zero-millisecond timer to schedule
> > things after the next event run, but changing
> > 
> > sleep(10)
> > 
> > To:
> > 
> > QTimer.singleShot(0, lambda: sleep(10))
> > 
> > Seemed like it should do that.  It doesn't.  Apparently the
> > processor.process() method is still blocking.   Where am I going wrong
> > here?
> 
> What this actually does is to start a single-shot QTimer (timing out
> immediately) to run a callback during the next run of the event-loop;
> Thus far, you understood things correctly. However, _INSIDE_ this
> callback, you still set the GUI-thread and, as a consequence, the
> event-loop to sleep for 10 seconds. This is obviously not what you
> wanted... A better idea would be to call
> 
> QTimer.singleShot(1, your_actual_processing_callback)
> 
> which delivers a timeout event triggering your callback after 10 seconds
> (1 ms).
> The difference is that a QTimer runs asynchronously in a thread by
> itself, while sleep runs synchronously in the thread it is called in,
> thus blocking the event loop which does the same.

I think I confused everyone with the sleep(10) calls; the intention wasn't to 
actually have a ten second delay, but just to have a place-holder for some 
real call that might take 10 seconds or more, such as a file copy, subprocess 
call, etc.

Anyway, I finally solved my problem using threads; by making processor 
subclass QThread instead of QObject, renaming "process()" to "run()" and 
connecting the gobutton to processor.start() I got the correct behavior.

Thanks for your response.
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt


Re: [PyQt] Processing signals from a called method while the method executes

2010-07-02 Thread Jan Haag
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 7/2/10 3:38 PM, alanm wrote:
> On Friday 02 July 2010 1:17:06 am Andreas Pakulat wrote:
>>
>> Don't block the event-loop with your processor. The signals are
>> delivered as you expect, but the widget is not redrawn with that
>> message. The reason is that your processing blocks the Qt event loop and
>> hence no painting is done.
>>
>> Possible options to not block the event loop that long would be to use a
>> QTimer to schedule each part of your processing after the next
>> event-loop run. The other option would be moving the processing into a
>> separate thread, you should only go this route after making familiar
>> with multi-threading though.
>>
>> Andreas
> 
> Thanks for the reply.  I don't think I understand, though.  I read in the 
> QTimer documentation where I can do a zero-millisecond timer to schedule 
> things after the next event run, but changing
> 
> sleep(10)
> 
> To:
> 
> QTimer.singleShot(0, lambda: sleep(10))
> 
> Seemed like it should do that.  It doesn't.  Apparently the 
> processor.process() method is still blocking.   Where am I going wrong here?

What this actually does is to start a single-shot QTimer (timing out
immediately) to run a callback during the next run of the event-loop;
Thus far, you understood things correctly. However, _INSIDE_ this
callback, you still set the GUI-thread and, as a consequence, the
event-loop to sleep for 10 seconds. This is obviously not what you
wanted... A better idea would be to call

QTimer.singleShot(1, your_actual_processing_callback)

which delivers a timeout event triggering your callback after 10 seconds
(1 ms).
The difference is that a QTimer runs asynchronously in a thread by
itself, while sleep runs synchronously in the thread it is called in,
thus blocking the event loop which does the same.

The processing callback should be reasonably short-running, otherwise
you'll run into the same problem again; in this case, your best bet is
to work your way into multithreading using the QThread class and
triggering your processing-thread's run method as the timer callback.
However, threads are often a good way to mess things up completely
(deadlocks etc...), so don't go for them unless you really have to.

Jan
-BEGIN PGP SIGNATURE-
Version: GnuPG/MacGPG2 v2.0.14 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQIcBAEBAgAGBQJMLhvdAAoJEJY4GpQWZadM80EP/iEhiNdKICnezSYwaknTs/Fv
GyV9J6LDi+jfj8wf9yMfFxoUp0Qwlu+ncAPMq5MIZG95HPepKEzPn9JY7dA9WfsP
+Ehkyb5LiutL3lZCWvHoujFK4zv4XQJJt+llPCOTEjgw93EM2X9UNYcIeTucN6J/
LMSJIldfgBBLzr4NNal3nPEutfM7QTs6FqZ08+P9bBs/cOqf0Y5UbWmwhBxUAPnv
zOus/DmQ7GVZcpdoyvjdtmA2JAHJJ8DyJeJC7deOHFVA+E+2Lfu4Uvl+QHZzKGKa
fQEySvtG6QvITyNloJvpYozfAM8Rv/Wwb5sIOc8u2cLmUZ0K7UvrN/NK6Y+yhfe+
/NVGKSpoTHeW21ib4q5rK2/tGZ9iCvJRtfmLLGUDWvLlm/OW1Jro2kowXeZAJmmH
MVLOMofQOs8ZlefgVwGn2CavMTHDH/lSnLQ/thpQgE0s4Y0M5lANn1TTPM+n5GWf
eIIaqc1tzJQI9cdwL6rhbdP3R8Q9EMKMPjupWhC5gEy8SAIMWv1vRD6qVym57ov/
TBoYlEUgx0K1xJMFcCKCwsfI2sUNzL/BYKMf5eG54ij/KxPDhS3Kg6y2IGXglm9r
e/ZPIgqBjhbFMxznYui3o2rATPOUU5T7ChP9ONq+R4PCCNWV6L1u/sErqe2c/Fid
jpN5/NBrXHrPzAeFxuEv
=Cowg
-END PGP SIGNATURE-


0x1665A74C.asc
Description: application/pgp-keys


0x1665A74C.asc.sig
Description: Binary data
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Re: [PyQt] Processing signals from a called method while the method executes

2010-07-02 Thread alanm
On Friday 02 July 2010 1:17:06 am Andreas Pakulat wrote:
> 
> Don't block the event-loop with your processor. The signals are
> delivered as you expect, but the widget is not redrawn with that
> message. The reason is that your processing blocks the Qt event loop and
> hence no painting is done.
> 
> Possible options to not block the event loop that long would be to use a
> QTimer to schedule each part of your processing after the next
> event-loop run. The other option would be moving the processing into a
> separate thread, you should only go this route after making familiar
> with multi-threading though.
> 
> Andreas

Thanks for the reply.  I don't think I understand, though.  I read in the 
QTimer documentation where I can do a zero-millisecond timer to schedule 
things after the next event run, but changing

sleep(10)

To:

QTimer.singleShot(0, lambda: sleep(10))

Seemed like it should do that.  It doesn't.  Apparently the 
processor.process() method is still blocking.   Where am I going wrong here?
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt


Re: [PyQt] Processing signals from a called method while the method executes

2010-07-01 Thread Andreas Pakulat
On 01.07.10 21:35:44, alan moore wrote:
> I've encountered this problem twice now in subtle ways, I think this
> is at the root of my last question about the QWebView; I've included
> sample code this time to illustrate.
> 
> In the attached script, I have a widget class and a processor class.
> The processor represents some kind of processing engine that's going
> to do a lengthy multi-part routine of some kind.  The widget class
> is the gui for the engine.
> 
> The "go" button is connected to the "process" method of the
> processor object.  The process() method emits a signal with a
> string, does process A for 10 seconds, emits a signal with a string,
> does process B for 10 seconds, and emits a final signal with a
> string.
> 
> The widget class is supposed to be picking up the signals and
> displaying the strings. So the expected output is:
> 
> 
> first message displays
> 
> second message displays
> 
> final message displays
> 
> The actual output is that nothing happens for 20 seconds, then all
> the text displays.  Because the widget isn't going to process any
> received signals until the called method exits.
> 
> How do I produce the expected behavior here?

Don't block the event-loop with your processor. The signals are
delivered as you expect, but the widget is not redrawn with that
message. The reason is that your processing blocks the Qt event loop and
hence no painting is done.

Possible options to not block the event loop that long would be to use a
QTimer to schedule each part of your processing after the next
event-loop run. The other option would be moving the processing into a
separate thread, you should only go this route after making familiar
with multi-threading though.

Andreas

-- 
Break into jail and claim police brutality.
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt