Discussion:
window destroy and re-create problem
Matthew Cahn
2006-06-07 21:40:40 UTC
Permalink
I have a rather elaborate image viewing application. A brief
description: the main GUI uses a wx.SplitterWindow. In the left-hand
pane is a wx.TreeCtrl for choosing sets of images (directory names or
database entries). In the right-hand pane is a wx.ScrolledWindow
containing thumbnail images (each of which is a wx.StaticBitmap and a
wx.StaticText in a wx.Panel).

Whenever the user clicks on a different set of images on the left (or
selects a different size for the thumbnails), I destroy the
wx.ScrolledWindow and make a new one containing the new thumbnails.
Sometimes this works, and sometimes the application silently exits.
This behavior recently got much worse when I added a gamma correction to
the thumbnails, that is, there's more computation before the creation of
the new wx.ScrolledWindow. Now it exits about half the time.

From other messages on the mailing list, it seems like this might have
to do with destroying the wx.ScrolledWindow while there are still events
pending. I put the destroy in a wx.CallAfter, and then the re-creation
in a second wx.CallAfter, but this seems to destroy the window _after_ I
create it. Is there a good strategy for handling any pending events,
destroying the window, and then creating the window, all in the right
order? Or am I barking up the wrong tree in trying to fix my silent
exit? Here's the bit of code that does the destroy/create:

class MainFrame(wx.Frame):
...
def createThumbPanel(self, parent, id, size=wx.DefaultSize):
wx.CallAfter(self._destroyThumbPanel)
wx.CallAfter(self._createThumbPanel, parent, id, size=size)

def _destroyThumbPanel(self):
try:
rv = self.thumbPanel.Destroy()
except AttributeError, err: # No thumb panel the first time
pass

def _createThumbPanel(self, parent, id, size=wx.DefaultSize):
self.thumbPanel = IVthumbs.ThumbPanel(parent, id, size=size,
style=wx.WANTS_CHARS)
self.splitter.SplitVertically(self.navTreePanel,
self.thumbPanel, navPanelWidth)
self.splitter.SetMinimumPaneSize(20)
self.splitter.SetSashPosition(navPanelWidth + scrollBarWidth)
self.thumbPanel.Bind(wx.EVT_CHAR, self.processKeys, self.thumbPanel)
...

Any help appreciated,
Matthew
--
--------------------------------
| Matthew Cahn
| Principal Systems Analyst
| Bristol-Myers Squibb Company
| Mailbox code: H23-05
| P.O. Box 4000
| Princeton, NJ 08543-4000
|
| Phone: (609) 252-3477
| Fax: (609) 252-6030
| Email: ***@bms.com
| Pager: ***@imbta.com
--------------------------------
Robin Dunn
2006-06-07 22:17:01 UTC
Permalink
Post by Matthew Cahn
I have a rather elaborate image viewing application. A brief
description: the main GUI uses a wx.SplitterWindow. In the left-hand
pane is a wx.TreeCtrl for choosing sets of images (directory names or
database entries). In the right-hand pane is a wx.ScrolledWindow
containing thumbnail images (each of which is a wx.StaticBitmap and a
wx.StaticText in a wx.Panel).
Whenever the user clicks on a different set of images on the left (or
selects a different size for the thumbnails), I destroy the
wx.ScrolledWindow and make a new one containing the new thumbnails.
Sometimes this works, and sometimes the application silently exits.
This behavior recently got much worse when I added a gamma correction to
the thumbnails, that is, there's more computation before the creation of
the new wx.ScrolledWindow. Now it exits about half the time.
From other messages on the mailing list, it seems like this might have
to do with destroying the wx.ScrolledWindow while there are still events
pending. I put the destroy in a wx.CallAfter, and then the re-creation
in a second wx.CallAfter, but this seems to destroy the window _after_ I
create it.
In some cases the order that the callafter's are executed will not be as
expected. I think this is due to the first one starting to run but does
something that causes some idle events to be fired. That then tells the
app to look at more pending events and so it runs the next one in the
queue. Eventually control returns to the first callafter function and
it finishes running and returns, making it appear that the first one ran
second.
Post by Matthew Cahn
Is there a good strategy for handling any pending events,
destroying the window, and then creating the window, all in the right
order?
One way to do it would be to just Hide your current scrolled window and
then make the new one immediately. Then use a wx.CallAfter to destroy
the old one.

Or instead of using both wx.CallAfter's at the same time, move the
second one so it is not called until the end of the first function.
--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!
Josiah Carlson
2006-06-07 23:42:14 UTC
Permalink
Post by Matthew Cahn
I have a rather elaborate image viewing application. A brief
description: the main GUI uses a wx.SplitterWindow. In the left-hand
pane is a wx.TreeCtrl for choosing sets of images (directory names or
database entries). In the right-hand pane is a wx.ScrolledWindow
containing thumbnail images (each of which is a wx.StaticBitmap and a
wx.StaticText in a wx.Panel).
Whenever the user clicks on a different set of images on the left (or
selects a different size for the thumbnails), I destroy the
wx.ScrolledWindow and make a new one containing the new thumbnails.
Sometimes this works, and sometimes the application silently exits.
This behavior recently got much worse when I added a gamma correction to
the thumbnails, that is, there's more computation before the creation of
the new wx.ScrolledWindow. Now it exits about half the time.
Or alternatively, don't destroy the ScrolledWindow, update the
StaticText and the Bitmap (or whatever you are using for showing the
thumbnails) as necessary.

- Josiah
Matthew Cahn
2006-06-08 20:14:58 UTC
Permalink
Thanks. One window (the one with the thumbnails) is destroyed and
re-created. Another window (containing the selected image) follows the
approach you suggest -- the bitmap and label get redrawn. Since the
image window seems to be part of the problem, I'm not sure changing the
approach on the thumbnail window would help. Also the number of
thumbnails varies so it would problematic not to destroy them.

Matthew
Post by Josiah Carlson
Post by Matthew Cahn
I have a rather elaborate image viewing application. A brief
description: the main GUI uses a wx.SplitterWindow. In the left-hand
pane is a wx.TreeCtrl for choosing sets of images (directory names or
database entries). In the right-hand pane is a wx.ScrolledWindow
containing thumbnail images (each of which is a wx.StaticBitmap and a
wx.StaticText in a wx.Panel).
Whenever the user clicks on a different set of images on the left (or
selects a different size for the thumbnails), I destroy the
wx.ScrolledWindow and make a new one containing the new thumbnails.
Sometimes this works, and sometimes the application silently exits.
This behavior recently got much worse when I added a gamma correction to
the thumbnails, that is, there's more computation before the creation of
the new wx.ScrolledWindow. Now it exits about half the time.
Or alternatively, don't destroy the ScrolledWindow, update the
StaticText and the Bitmap (or whatever you are using for showing the
thumbnails) as necessary.
- Josiah
---------------------------------------------------------------------
--
--------------------------------
| Matthew Cahn
| Principal Systems Analyst
| Bristol-Myers Squibb Company
| Mailbox code: H23-05
| P.O. Box 4000
| Princeton, NJ 08543-4000
|
| Phone: (609) 252-3477
| Fax: (609) 252-6030
| Email: ***@bms.com
| Pager: ***@imbta.com
--------------------------------
Matthew Cahn
2006-06-08 20:07:19 UTC
Permalink
Thanks for the explanation and advice. I tried the approach of putting
the second CallAfter function at the end of the first. In reality
there's a longer series of things that needs to happen in a particular
order, so I chained them one after the other with this approach. It's
not clear that this helped. There's another frame I didn't mention --
the window containing the image represented by the currently-selected
thumbnail. Temporarily commenting-out the code that brings up the image
window seems to fix the silent exit, so I also put the maniuplations of
the image window in the CallAfter series. But the app still silently
exits sometimes.

Removing the gamma correction on the image window helps. That implies
the window is ready for events sooner.

Is there a way to see all the events that are being processed, and
perhaps by which window? That might tell me if the problem really does
have to do with sending events to windows that aren't there.

Is there any other common cause of silent exits?

Thanks again,
Matthew
Post by Robin Dunn
Post by Matthew Cahn
I have a rather elaborate image viewing application. A brief
description: the main GUI uses a wx.SplitterWindow. In the left-hand
pane is a wx.TreeCtrl for choosing sets of images (directory names or
database entries). In the right-hand pane is a wx.ScrolledWindow
containing thumbnail images (each of which is a wx.StaticBitmap and a
wx.StaticText in a wx.Panel).
Whenever the user clicks on a different set of images on the left (or
selects a different size for the thumbnails), I destroy the
wx.ScrolledWindow and make a new one containing the new thumbnails.
Sometimes this works, and sometimes the application silently exits.
This behavior recently got much worse when I added a gamma correction
to the thumbnails, that is, there's more computation before the
creation of the new wx.ScrolledWindow. Now it exits about half the
time.
From other messages on the mailing list, it seems like this might
have to do with destroying the wx.ScrolledWindow while there are
still events pending. I put the destroy in a wx.CallAfter, and then
the re-creation in a second wx.CallAfter, but this seems to destroy
the window _after_ I create it.
In some cases the order that the callafter's are executed will not be
as expected. I think this is due to the first one starting to run but
does something that causes some idle events to be fired. That then
tells the app to look at more pending events and so it runs the next
one in the queue. Eventually control returns to the first callafter
function and it finishes running and returns, making it appear that
the first one ran second.
Post by Matthew Cahn
Is there a good strategy for handling any pending events,
destroying the window, and then creating the window, all in the right
order?
One way to do it would be to just Hide your current scrolled window
and then make the new one immediately. Then use a wx.CallAfter to
destroy the old one.
Or instead of using both wx.CallAfter's at the same time, move the
second one so it is not called until the end of the first function.
--
--------------------------------
| Matthew Cahn
| Principal Systems Analyst
| Bristol-Myers Squibb Company
| Mailbox code: H23-05
| P.O. Box 4000
| Princeton, NJ 08543-4000
|
| Phone: (609) 252-3477
| Fax: (609) 252-6030
| Email: ***@bms.com
| Pager: ***@imbta.com
--------------------------------
Robin Dunn
2006-06-08 21:42:09 UTC
Permalink
Post by Matthew Cahn
Is there a way to see all the events that are being processed, and
perhaps by which window? That might tell me if the problem really does
have to do with sending events to windows that aren't there.
Not built-in. You would essentially have to bind a handler for all
events, for all widgets. PythonCard has a tool that can do this, it
would be nice to have something similar for use in raw wxPython too.
Post by Matthew Cahn
Is there any other common cause of silent exits?
Not really common, but there are a few. What platform are you on? Do
you use threads? (Oops, I almost typed that as "threats" ;-) Is it
really silent (IOW, nothing is printed on the console you started the
app from?)
--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!
Matthew Cahn
2006-06-09 02:50:20 UTC
Permalink
Platform: WinXP SP1, Python 2.3.4

Yes, it uses threads. Whenever the user navigates to a new image
(including when a set of images is first displayed), a thread loads into
memory whatever the next image is likely to be. The image-loading
threads are not doing anything to the GUI, I believe. I could certainly
try shutting off that feature.

I tried threats too, but it still exited silently ;-)

Yes, it's totally silent. The DOS command window simply returns to the
next DOS prompt. Running it with pdb also just returns to the DOS prompt.

I'd like to try it under Linux also, but will have to deal with some
SuSE Linux installation difficulties first.

Matthew

----- Original Message -----
From: Robin Dunn <***@alldunn.com>
Date: Thursday, June 8, 2006 5:42 pm
Subject: Re: [wxPython-users] window destroy and re-create problem
Post by Matthew Cahn
Post by Matthew Cahn
Is there a way to see all the events that are being processed,
and
Post by Matthew Cahn
perhaps by which window? That might tell me if the problem
really does
Post by Matthew Cahn
have to do with sending events to windows that aren't there.
Not built-in. You would essentially have to bind a handler for all
events, for all widgets. PythonCard has a tool that can do this,
it
would be nice to have something similar for use in raw wxPython too.
Post by Matthew Cahn
Is there any other common cause of silent exits?
Not really common, but there are a few. What platform are you on?
Do
you use threads? (Oops, I almost typed that as "threats" ;-) Is
it
really silent (IOW, nothing is printed on the console you started
the
app from?)
--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!
--------------------------------------------------------------------
-
For additional commands, e-mail: wxPython-users-
Loading...