[wx-dev] #9563: Nasty flickering when wxScrolledWindow and wxPanel are combined

wxTrac noreply at wxsite.net
Wed Jun 11 02:09:08 PDT 2008


Ticket URL: <http://trac.wxwidgets.org/ticket/9563>

#9563: Nasty flickering when wxScrolledWindow and wxPanel are combined
---------------------------+------------------------------------------------
 Reporter:  hajokirchhoff  |       Owner:         
     Type:  defect         |      Status:  new    
 Priority:  high           |   Milestone:  2.8.9  
Component:  GUI-generic    |     Version:  2.9-svn
 Keywords:  flicker        |   Blockedby:         
    Patch:  1              |    Blocking:         
---------------------------+------------------------------------------------
 Widgets hierarchy is as follows:
 wxScrolledWindow
    wxPanel
       wxTextCtrl
       wxComboCtrl
       <other widgets>

 When one of the children of the wxPanel gets the focus and the
 wxScrolledWindow is too small to display the entire panel, the
 scrollhelper will first

 a) scroll to the bottom of the panel   and then
 b) will make the child control visible

 The effect is that with _every_ focus change event, the entire scrolled
 window first scrolls to the bottom right, then scrolls back up to the
 correct position. This does not happen, when the child widgets are
 immediate children of the wxScrolledWindow. It only happens when the
 widgets are children of a wxPanel which in turn is a child of the
 wxScrolledWindow.

 The problem is that when the focus changes, the wxPanel propagates its
 wxFocus event upwards.

 containr.cpp:181
 // propagate the last focus upwards so that our parent can set focus back
 // to us if it loses it now and regains later; do *not* do this if we are
 // a toplevel window (e.g. wxDialog) that has another frame as its parent

 So what seems to happen is:
 A focus event is sent.
 wxPanel sees this event and calls
             parent->GetEventHandler()->ProcessEvent(eventFocus);
 wxScrollHelper intercepts this event and assumes that the wxPanel is about
 to get the focus. It scrolls the wxScrolledWindow accordingly. Since the
 wxScrolledWindow is too small to show the entire panel, it scrolls to the
 bottom/right corner.
 Normal event handling continues, the child widget receives the focus and
 the wxScrolledWindow::HandleEvent sees this event again. The
 wxScrollHelper will act on the event and scroll the actual child window
 into view.

 To sum it up: The problem seems to be that the event gets duplicated in
 containr.cpp, where it is propagated from the wxPanel to the parent
 wxScrolledWindow. The effect is that wxScrolledHelper sees the event twice
 and one of the events pretends to be a set focus event for the wxPanel.

 I don't know how to fix this at the moment and would like to get some
 input. My first impulse was to add a
 if (wxDynamicCast(win, wxPanel)!=0)
    return;

 to the wxScrollHelper::HandleOnChildFocus, IOW: ignoring all events where
 a wxPanel is the child. wxPanels as a child would never be scrolled
 automatically. But that would disable automatic scrolling for widgets
 derived from wxPanel as well.

 A better approach might be
 if (win->AcceptsFocus()==false)
    return;

 Widgets that do not accept a focus should not be handled by
 HandleOnChildFocus. They should normally not even get a focus event, but
 in this special wxPanel case they do. So simply return in this case and do
 nothing.


--
Ticket URL: <http://trac.wxwidgets.org/ticket/9563>


More information about the wx-dev mailing list