Need help w/ GenericMessageDialog, please

OlyDLG wrote:

Hi! Think I'm missing something basic: I'm trying to create a reusable
instance of GenericMessageDialog as my "About" Dialog, and initially use
it as a splash screen. Thus I have the following code:

class App(wx.App):
def OnInit(self):
self.AboutBox = Dialogs.VPGenericMessageDialog(None, "My Info", "About")
# VPGenericMessageDialog is a thin wrapper around the GMD c-tor
self.SetTopWindow(self.AboutBox)
self.AboutBox.Fit()
self.AboutBox.Show()
:
# Code that takes noticeable time to run, thus the desire for a splash
screen
:
self.frame = MainFrame(None)
self.SetTopWindow(self.frame)
self.frame.Fit()
self.frame.Show()
return True

if __name__ == '__main__':
app = App(0)
app.MainLoop()

It works, except that the content of AboutBox isn't displayed until
_after_ all the "code that takes noticeable time to run" has finished,
thus defeating its use as a splash screen. (To be a little more
specific, the controls in which the content should be--and eventually
is--displayed, are visible as empty, white-ish rectangles set against
the general blue background of the GMD.) I've tried various combinations
of commenting out the self.SetTopWindow(self.AboutBox) and
self.AboutBox.Fit() lines, to no avail. How do I force these controls to
display their content before the program moves on?

Since you haven't entered MainLoop yet then there is no opportunity for the window to receive paint (or any other) events, and so they are never drawn on screen until after your long-running stuff completes and you finally do enter the main event loop.

It might work if you just call wx.Yield after the Show(), then there will be a temporary event loop that will enable the about box to paint itself, however things may still be frozen while the long-running code is running because it still can't deliver any further events until the MainLoop is reached. If that becomes a problem then you may want to run your long-running stuff on a thread so the GUI can enter MainLoop right away, and then when the initialization stuff is done it can send a signal to the UI thread so it will create the MainFrame and hide the AboutBox.

···

--
Robin Dunn
Software Craftsman

Ah, thanks, Robin, not quite as elementary as I had thought; I’ll try wx.Yield first, and then the thread method…unless there’s a more “wxpythonic” way to do what I’m trying to do, namely, display what amounts to a splash screen (though I want to use GMD instead of wx.SplashScreen) while some time-consuming overhead is being taken care of, and then display the main frame when that overhead is done. Thanks again!

···

On Friday, March 8, 2013 7:22:25 PM UTC-8, Robin Dunn wrote:

OlyDLG wrote:

Hi! Think I’m missing something basic: I’m trying to create a reusable

instance of GenericMessageDialog as my “About” Dialog, and initially use

it as a splash screen. Thus I have the following code:

class App(wx.App):

def OnInit(self):

self.AboutBox = Dialogs.VPGenericMessageDialog(None, “My Info”, “About”)

VPGenericMessageDialog is a thin wrapper around the GMD c-tor

self.SetTopWindow(self.AboutBox)

self.AboutBox.Fit()

self.AboutBox.Show()

:

Code that takes noticeable time to run, thus the desire for a splash

screen

:

self.frame = MainFrame(None)

self.SetTopWindow(self.frame)

self.frame.Fit()

self.frame.Show()

return True

if name == ‘main’:

app = App(0)

app.MainLoop()

It works, except that the content of AboutBox isn’t displayed until

after all the “code that takes noticeable time to run” has finished,

thus defeating its use as a splash screen. (To be a little more

specific, the controls in which the content should be–and eventually

is–displayed, are visible as empty, white-ish rectangles set against

the general blue background of the GMD.) I’ve tried various combinations

of commenting out the self.SetTopWindow(self.AboutBox) and

self.AboutBox.Fit() lines, to no avail. How do I force these controls to

display their content before the program moves on?

Since you haven’t entered MainLoop yet then there is no opportunity for
the window to receive paint (or any other) events, and so they are never
drawn on screen until after your long-running stuff completes and you
finally do enter the main event loop.

It might work if you just call wx.Yield after the Show(), then there
will be a temporary event loop that will enable the about box to paint
itself, however things may still be frozen while the long-running code
is running because it still can’t deliver any further events until the
MainLoop is reached. If that becomes a problem then you may want to run
your long-running stuff on a thread so the GUI can enter MainLoop right
away, and then when the initialization stuff is done it can send a
signal to the UI thread so it will create the MainFrame and hide the
AboutBox.


Robin Dunn

Software Craftsman

http://wxPython.org

wx.Yield() worked, thanks again!

OlyDLG

···

On Friday, March 8, 2013 8:04:04 PM UTC-8, OlyDLG wrote:

Ah, thanks, Robin, not quite as elementary as I had thought; I’ll try wx.Yield first, and then the thread method…unless there’s a more “wxpythonic” way to do what I’m trying to do, namely, display what amounts to a splash screen (though I want to use GMD instead of wx.SplashScreen) while some time-consuming overhead is being taken care of, and then display the main frame when that overhead is done. Thanks again!

On Friday, March 8, 2013 7:22:25 PM UTC-8, Robin Dunn wrote:

OlyDLG wrote:

Hi! Think I’m missing something basic: I’m trying to create a reusable

instance of GenericMessageDialog as my “About” Dialog, and initially use

it as a splash screen. Thus I have the following code:

class App(wx.App):

def OnInit(self):

self.AboutBox = Dialogs.VPGenericMessageDialog(None, “My Info”, “About”)

VPGenericMessageDialog is a thin wrapper around the GMD c-tor

self.SetTopWindow(self.AboutBox)

self.AboutBox.Fit()

self.AboutBox.Show()

:

Code that takes noticeable time to run, thus the desire for a splash

screen

:

self.frame = MainFrame(None)

self.SetTopWindow(self.frame)

self.frame.Fit()

self.frame.Show()

return True

if name == ‘main’:

app = App(0)

app.MainLoop()

It works, except that the content of AboutBox isn’t displayed until

after all the “code that takes noticeable time to run” has finished,

thus defeating its use as a splash screen. (To be a little more

specific, the controls in which the content should be–and eventually

is–displayed, are visible as empty, white-ish rectangles set against

the general blue background of the GMD.) I’ve tried various combinations

of commenting out the self.SetTopWindow(self.AboutBox) and

self.AboutBox.Fit() lines, to no avail. How do I force these controls to

display their content before the program moves on?

Since you haven’t entered MainLoop yet then there is no opportunity for
the window to receive paint (or any other) events, and so they are never
drawn on screen until after your long-running stuff completes and you
finally do enter the main event loop.

It might work if you just call wx.Yield after the Show(), then there
will be a temporary event loop that will enable the about box to paint
itself, however things may still be frozen while the long-running code
is running because it still can’t deliver any further events until the
MainLoop is reached. If that becomes a problem then you may want to run
your long-running stuff on a thread so the GUI can enter MainLoop right
away, and then when the initialization stuff is done it can send a
signal to the UI thread so it will create the MainFrame and hide the
AboutBox.


Robin Dunn

Software Craftsman

http://wxPython.org