[...] Also, 90% of my menu items will need to be disabled, because I can only have one process using the COM port at any one time. It seems like a pain to have to add each new menu item to a method which disables/enables it all the time. [...]
I prefer a busy dialog (like the one provided in wxBusyInfo), or locking the GUI like I am doing (but with a busy cursor ;o) ). FWIW, I tried the wxWindowDisabler as suggested and it does exactly the same thing. As soon as I call wxYield (or wxSafeYield), the cursor reverts back to 'non-busy'. [...]
In your situation, I'd make only a few changes. Given that you are essentially disabling the entire application while your thread is running, then using wxWindowDisabler or a busy dialog does seem to be a better solution than simply disabling menu options. (That would be appropriate if you were disallowing only a few features, but not for wholesale disabling like you're doing.)
I don't understand the need to use wxYield() or wxSafeYield(). Your communication process is running in another thread, so it won't be automatically locking your GUI -- that's the whole point of spawning a separate thread. If you need to send updates to your main thread (whether to update the status bar or to update text on a busy dialog), you can do that either by posting an EVT_UPDATE_UI, or (my preference) by using a Queue and wxWakeUpIdle() in conjuction with idle event handling in your main thread. Your thread puts some sort of message in the Queue and then calls wxWakeUpIdle(), and your idle handler checks the Queue and makes whatever updates are appropriate. Your main thread can set a busy cursor when you launch the worker thread, and reset it to a normal cursor when the worker thread sends a message that indicates that it's finished.
I would create a (possibly modal) busy dialog, which would launch the worker thread. I'd have the worker thread post custom idle events back to the main app, and I'd have the busy dialog update itself based on the status reported in those idle events. When the busy dialog gets closed, the busy cursor can be turned off as well..
Jeff Shannon
Technician/Programmer
Credit International
OK, eventually I will let this thread die, but a couple more questions:
For complicated cases, I like your approach, Jeff, and will probably end up using it. But is there anything wrong with the following?
wxBeginBusyCursor()
..start up thread called mythread to do long task
while mythread.isAlive():
wxGetApp().ProcessIdle()
wxEndBusyCursor()
Then, in my OnIdle event handler...
def OnIdle(self, event):
if wxGetApp().Pending():
wxGetApp().Dispatch()
This seems to work just fine. My upload process is happily creating windows and crap on my GUI. HOWEVER - it still leaves the GUI wide open. So - fine, I wrap it with the creation and destruction of a wxWindowDisabler. Great, the GUI updates, and is disabled from user input - but the damn cursor goes back to a non-busy state as soon as wxWindowDisabler is instantiated! Why is this occuring! Even if I explicitly set the cursor to wxHOURGLASS_CURSOR, it has no effect. This is driving me nuts! Any ideas?
Mark.
Jeff Shannon wrote:
···
In your situation, I'd make only a few changes. Given that you are essentially disabling the entire application while your thread is running, then using wxWindowDisabler or a busy dialog does seem to be a better solution than simply disabling menu options. (That would be appropriate if you were disallowing only a few features, but not for wholesale disabling like you're doing.) I don't understand the need to use wxYield() or wxSafeYield(). Your communication process is running in another thread, so it won't be automatically locking your GUI -- that's the whole point of spawning a separate thread. If you need to send updates to your main thread (whether to update the status bar or to update text on a busy dialog), you can do that either by posting an EVT_UPDATE_UI, or (my preference) by using a Queue and wxWakeUpIdle() in conjuction with idle event handling in your main thread. Your thread puts some sort of message in the Queue and then calls wxWakeUpIdle(), and your idle handler checks the Queue and makes whatever updates are appropriate. Your main thread can set a busy cursor when you launch the worker thread, and reset it to a normal cursor when the worker thread sends a message that indicates that it's finished.
I would create a (possibly modal) busy dialog, which would launch the worker thread. I'd have the worker thread post custom idle events back to the main app, and I'd have the busy dialog update itself based on the status reported in those idle events. When the busy dialog gets closed, the busy cursor can be turned off as well..
Jeff Shannon
Technician/Programmer
Credit International
OK! I figured this out finally. If I say self.CaptureMouse() before I call wxBeginBusyCursor() and THEN create my WindowDisabler, the cursor stays busy! Then I simply call wxEndBusyCursor and self.ReleaseMouse() when I am done.
Whew! Out of curiosity - is there anything wrong with handling the threading in the following manner (same as I posted last time)?
When you change the cursor, its only for the window you run the method in.
When I change the cursor, I recurse thought my entire window list and
change the cursor everyway. I'm not sure how this reacts in the Window
Disabler, however.
Nigel
···
On Thu, 16 Jan 2003 15:59:22 -0500 Mark Melvin <Mark.Melvin@dspfactory.com> wrote:
OK, eventually I will let this thread die, but a couple more questions:
For complicated cases, I like your approach, Jeff, and will probably end
up using it. But is there anything wrong with the following?
wxBeginBusyCursor()
..start up thread called mythread to do long task
while mythread.isAlive():
wxGetApp().ProcessIdle()
wxEndBusyCursor()
Then, in my OnIdle event handler...
def OnIdle(self, event):
if wxGetApp().Pending():
wxGetApp().Dispatch()
This seems to work just fine. My upload process is happily creating
windows and crap on my GUI. HOWEVER - it still leaves the GUI wide
open. So - fine, I wrap it with the creation and destruction of a
wxWindowDisabler. Great, the GUI updates, and is disabled from user
input - but the damn cursor goes back to a non-busy state as soon as
wxWindowDisabler is instantiated! Why is this occuring! Even if I
explicitly set the cursor to wxHOURGLASS_CURSOR, it has no effect. This
is driving me nuts! Any ideas?
Mark.
Jeff Shannon wrote:
> In your situation, I'd make only a few changes. Given that you are
> essentially disabling the entire application while your thread is
> running, then using wxWindowDisabler or a busy dialog does seem to be
> a better solution than simply disabling menu options. (That would be
> appropriate if you were disallowing only a few features, but not for
> wholesale disabling like you're doing.)
> I don't understand the need to use wxYield() or wxSafeYield(). Your
> communication process is running in another thread, so it won't be
> automatically locking your GUI -- that's the whole point of spawning a
> separate thread. If you need to send updates to your main thread
> (whether to update the status bar or to update text on a busy dialog),
> you can do that either by posting an EVT_UPDATE_UI, or (my preference)
> by using a Queue and wxWakeUpIdle() in conjuction with idle event
> handling in your main thread. Your thread puts some sort of message
> in the Queue and then calls wxWakeUpIdle(), and your idle handler
> checks the Queue and makes whatever updates are appropriate. Your
> main thread can set a busy cursor when you launch the worker thread,
> and reset it to a normal cursor when the worker thread sends a message
> that indicates that it's finished.
>
> I would create a (possibly modal) busy dialog, which would launch the
> worker thread. I'd have the worker thread post custom idle events
> back to the main app, and I'd have the busy dialog update itself based
> on the status reported in those idle events. When the busy dialog
> gets closed, the busy cursor can be turned off as well..
>
> Jeff Shannon
> Technician/Programmer
> Credit International
---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org
--
Nigel W. Moriarty
Building 4R0230
Physical Biosciences Division
Lawrence Berkeley National Laboratory
Berkeley, CA 94720-8235
Phone : 510-486-5709
Fax : 510-486-5909
Email : NWMoriarty@LBL.gov
Web : CCI.LBL.gov