what's up when all sizers freeze?

Ever had all of your wxPython sizers just quit working? Like, you open your app, and try to click and drag the corner to test whether your nested sizers are all getting along, and nothing resizes itself? The frame itself resizes but none of the panels and their subpanels seem to be receiving any signals.

Does this sound familiar? It seemed to come out of nowhere. I logged out, rebooted, situation persists.

Eric Ongerth wrote:

Ever had all of your wxPython sizers just quit working? Like, you open your app, and try to click and drag the corner to test whether your nested sizers are all getting along, and nothing resizes itself? The frame itself resizes but none of the panels and their subpanels seem to be receiving any signals.

Does this sound familiar? It seemed to come out of nowhere. I logged out, rebooted, situation persists.

Make sure that you are actually doing the window.SetSizer(sizer) calls. All the sizer setup in the world won't do any good if you don't tell the window to use it. Also make sure that the proportion and wx.EXPAND flags are set appropriately for all the items that need to stretch. This includes the nested sizers if they contain the stretchable widgets, the sizer also needs to be stretchable in it's parent if the widget is going to stretch.

If these ideas don't help then make a small runnable sample of your layout and send it here. MakingSampleApps - wxPyWiki

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Thank you, Robin.

Yes, SetSizer() calls, etc., are the first place I searched for the cause. Strangely, I was not working anywhere near the sizer code when this happened; I made some minor change or other to a database class, last thing I remember before the sizer problem hit. One moment I had a working GUI/database application and the next it was useless. But I’m down to the last-chance theory that a random line or section must have gotten deleted somewhere, so I’ve scrutinized all window and sizer-related code closely.

At this point I’ve taken it as a sign that it’s time for a thorough code review, so I’m rebuilding the entire thing from parent windows downward, making sure each nesting and each class works properly. Surely a shake-up like this is beneficial, on occasion. I’ll make the best of it :expressionless:

···

On 6/2/07, Robin Dunn robin@alldunn.com wrote:

Eric Ongerth wrote:

Ever had all of your wxPython sizers just quit working? Like, you open
your app, and try to click and drag the corner to test whether your
nested sizers are all getting along, and nothing resizes itself? The

frame itself resizes but none of the panels and their subpanels seem to
be receiving any signals.

Does this sound familiar? It seemed to come out of nowhere. I logged
out, rebooted, situation persists.

Make sure that you are actually doing the window.SetSizer(sizer) calls.
All the sizer setup in the world won’t do any good if you don’t tell
the window to use it. Also make sure that the proportion and wx.EXPAND
flags are set appropriately for all the items that need to stretch.
This includes the nested sizers if they contain the stretchable widgets,
the sizer also needs to be stretchable in it’s parent if the widget is

going to stretch.

If these ideas don’t help then make a small runnable sample of your
layout and send it here. http://wiki.wxpython.org/MakingSampleApps


Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!


To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail:
wxPython-users-help@lists.wxwidgets.org

Found it!

Inside of TextCtrlAutoComplete.py, there is this basic handler which happens to be bound to both wx.EVT_SIZE and wx.EVT_MOVE not only of itself, but of all of its parents, grandparents…etc… all the way up the hierarchy.

    gp = self
    while ( gp != None ) :
        gp.Bind ( wx.EVT_MOVE , self.onControlChanged, gp )
        gp.Bind ( wx.EVT_SIZE , self.onControlChanged, gp )
        gp = gp.GetParent

()

    self.Bind( wx.EVT_KILL_FOCUS, self.onControlChanged, self )

def onControlChanged(self, event):
    self._showDropDown( False )
    event.Skip()

Well… somewhere in the middle of my working on relatively unrelated stuff last night, the event.Skip() line got commented out of that routing. I don’t know if it was just a mouse button slip as I was passing by, or what. But that only little event.Skip() got commented out, and as a result the TextCtrlAutoComplete holds up an entire branch of my main window. Everything from there on up is prevented from resizing because wx.EVT_SIZE is caught by one little control’s event handler and not skipped.

So I’m curious what can be learned from this. One must, of course, be responsible for one’s every move when programming, including accidentally commenting out even a single line. That is simply part of the trade. But, with that acknowledged, intuitively I feel that the TextCtrlAutoComplete should be built a little differently in order to not throw such great consequences to its whole parent system if the control itself is for some reason altered. I’m not trying to make a big point here, just taking it as a learning opportunity.

It strikes me as odd that a control should need to bind its On(self)Changed method to EVT_MOVE and EVT_SIZE at the level of each of its containers / ancestors. I remember when I first read through the control in order to start making use of it in my app, that recursive binding section bothered me a little bit but I decided to get back to that later.

Related thoughts?

Found it!

Inside of TextCtrlAutoComplete.py, there is this basic handler which happens
to be bound to both wx.EVT_SIZE and wx.EVT_MOVE **not only of itself, but of
all of its parents, grandparents...etc... all the way up the hierarchy**.

<code snipped>

Well... somewhere in the middle of my working on relatively unrelated stuff
last night, the event.Skip() line got commented out of that routing. I
don't know if it was just a mouse button slip as I was passing by, or what.
But that only little event.Skip() got commented out, and as a result the
TextCtrlAutoComplete holds up an entire branch of my main window.
Everything from there on up is prevented from resizing because wx.EVT_SIZE
is caught by one little control's event handler and not skipped.

So I'm curious what can be learned from this. One must, of course, be
responsible for one's every move when programming, including accidentally
commenting out even a single line. That is simply part of the trade. But,
with that acknowledged, intuitively I feel that the TextCtrlAutoComplete
should be built a little differently in order to not throw such great
consequences to its whole parent system if the control itself is for some
reason altered. I'm not trying to make a big point here, just taking it as
a learning opportunity.

It strikes me as odd that a control should need to bind its On(self)Changed
method to EVT_MOVE and EVT_SIZE at the level of *each* of its containers /
ancestors. I remember when I first read through the control in order to
start making use of it in my app, that recursive binding section bothered me
a little bit but I decided to get back to that later.

When you move a top level window, the children don't receive move
events, because a windows position is relative to its parent and that
hasn't changed. The PopupWindow is positioned absolutely, though, so
it needs to be updated and a recursive event handler is how the author
chose to implement it. The size event doesn't need to be in there.

This isn't how I'd implement it, though. I'd use an idle event handler
to sync the position and state.

Try replacing the recursive event handler with this:

self.Bind(wx.EVT_IDLE, self.EnsurePositionAndSize)

def EnsurePositionAndSize(self, evt):
    """ Make sure that the controls size and position
    match the parent controls current size and position"""
    #hax - the sizing code should be in a seperate method
    # called both here and from _showDropDown
    if self.dropdown.IsShown():
        self._showDropDown(True)

This has a behavior change, which I prefer. In the original code, when
the window was moved or resized with the dropdown shown, the dropdown
was hidden. This code keeps the dropdown shown, and just updates the
size and position. You can get the old behavior with some extra logic
to compare the size and position - this is left as an exercise for the
reader.

(If the original author [or anyone else] wants to add this to the
version on the wiki, feel free)

As for the problem with removing evt.Skip() causing problems, this is
a general problem you need to be aware of. It can even be platform
specific, where a missing evt.Skip() will have no visible effect on,
say, Windows but will prevent updates under Gtk. In general, you
should *always* Skip() unless you know exactly why you aren't, and
what behavior you are preventing by doing so. I'd like it if the
default changed so you had to explicitly block events instead of
explicitly skipping, but since it's a major change and would break
almost all currently working code, I don't really see much chance of
it happening.

···

On 6/2/07, Eric Ongerth <ericongerth@gmail.com> wrote:

Good explanations, Chris. Thank you. I think I will try your suggested change to idle-based rechecking. Looks like this may also help me track down a persistent PyDeadObjectError i’m getting from the same control (despite efforts to unsubscribe/disconnect before closing)… the error should then happen at first idle rather than some time later when motion or sizing may occur.

···

On 6/4/07, Chris Mellon arkanes@gmail.com wrote:

On 6/2/07, Eric Ongerth ericongerth@gmail.com wrote:

Found it!

Inside of TextCtrlAutoComplete.py, there is this basic handler which happens
to be bound to both wx.EVT_SIZE and wx.EVT_MOVE not only of itself, but of
all of its parents, grandparents…etc… all the way up the hierarchy
.

Well… somewhere in the middle of my working on relatively unrelated stuff

last night, the event.Skip() line got commented out of that routing. I
don’t know if it was just a mouse button slip as I was passing by, or what.
But that only little event.Skip() got commented out, and as a result the

TextCtrlAutoComplete holds up an entire branch of my main window.
Everything from there on up is prevented from resizing because wx.EVT_SIZE
is caught by one little control’s event handler and not skipped.

So I’m curious what can be learned from this. One must, of course, be
responsible for one’s every move when programming, including accidentally
commenting out even a single line. That is simply part of the trade. But,

with that acknowledged, intuitively I feel that the TextCtrlAutoComplete
should be built a little differently in order to not throw such great
consequences to its whole parent system if the control itself is for some

reason altered. I’m not trying to make a big point here, just taking it as
a learning opportunity.

It strikes me as odd that a control should need to bind its On(self)Changed
method to EVT_MOVE and EVT_SIZE at the level of each of its containers /

ancestors. I remember when I first read through the control in order to
start making use of it in my app, that recursive binding section bothered me
a little bit but I decided to get back to that later.

When you move a top level window, the children don’t receive move
events, because a windows position is relative to its parent and that
hasn’t changed. The PopupWindow is positioned absolutely, though, so

it needs to be updated and a recursive event handler is how the author
chose to implement it. The size event doesn’t need to be in there.

This isn’t how I’d implement it, though. I’d use an idle event handler

to sync the position and state.

Try replacing the recursive event handler with this:

self.Bind(wx.EVT_IDLE, self.EnsurePositionAndSize)

def EnsurePositionAndSize(self, evt):
“”" Make sure that the controls size and position

match the parent controls current size and position"""
#hax - the sizing code should be in a seperate method
# called both here and from _showDropDown
if self.dropdown.IsShown():

    self._showDropDown(True)

This has a behavior change, which I prefer. In the original code, when
the window was moved or resized with the dropdown shown, the dropdown
was hidden. This code keeps the dropdown shown, and just updates the

size and position. You can get the old behavior with some extra logic
to compare the size and position - this is left as an exercise for the
reader.

(If the original author [or anyone else] wants to add this to the

version on the wiki, feel free)

As for the problem with removing evt.Skip() causing problems, this is
a general problem you need to be aware of. It can even be platform
specific, where a missing evt.Skip
() will have no visible effect on,
say, Windows but will prevent updates under Gtk. In general, you
should always Skip() unless you know exactly why you aren’t, and
what behavior you are preventing by doing so. I’d like it if the

default changed so you had to explicitly block events instead of
explicitly skipping, but since it’s a major change and would break
almost all currently working code, I don’t really see much chance of

it happening.


To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org

For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org