Updating scrollbars after a wx.ScrolledWindow content size change

959 views
Skip to first unread message

Anders J. Munch

unread,
Dec 13, 2013, 6:02:28 AM12/13/13
to wxpytho...@googlegroups.com
I had a ScrolledWindow problem: When showing and hiding content
programmatically in a GridBagSizer within the ScrolledWindow, the
scrollbar didn't update.

I whittled my program down to the attached. Grab a corner and resize
the window, and the scrollbar updates perfectly, appearing and
disappearing as necessary. But when pressing Show and Hide buttons,
changing the size of the GridBagSizer, the scrollbar doesn't update
accordingly. Layout() doesn't help, AdjustScrollbars() doesn't help,
Refresh() doesn't help.

As a last resort, I called .Layout on the containing frame, and to my
great surprise, then it works!

Well, that solves my problem, but it conflicts with my understand of
how Layout works: It's the ScrolledWindow contents whose size is
changing, not the size of the ScrolledWindow itself, so there should
be no need to re-layout the outer container. Also, my experience has
been that Layout() only recurses through nested sizers, but once it
hits a wx.Panel it does not automatically layout the sizer of that
panel. So why should frame.Layout() have any effect on the innards of
a nested wx.Panel subclass?

Can someone explain why?

regards, Anders

scrolltest.py

Robin Dunn

unread,
Dec 18, 2013, 8:19:41 PM12/18/13
to wxpytho...@googlegroups.com
Anders J. Munch wrote:
> I had a ScrolledWindow problem: When showing and hiding content
> programmatically in a GridBagSizer within the ScrolledWindow, the
> scrollbar didn't update.
>
> I whittled my program down to the attached. Grab a corner and resize
> the window, and the scrollbar updates perfectly, appearing and
> disappearing as necessary. But when pressing Show and Hide buttons,
> changing the size of the GridBagSizer, the scrollbar doesn't update
> accordingly. Layout() doesn't help, AdjustScrollbars() doesn't help,
> Refresh() doesn't help.
>

You need to adjust the virtual size of the scrolled window to the new
needs of the sizer. Something like this:

w, h = self.sizer.GetMinSize()
self.SetVirtualSize( (w, h) )


> As a last resort, I called .Layout on the containing frame, and to my
> great surprise, then it works!
>
> Well, that solves my problem, but it conflicts with my understand of
> how Layout works: It's the ScrolledWindow contents whose size is
> changing, not the size of the ScrolledWindow itself, so there should
> be no need to re-layout the outer container. Also, my experience has
> been that Layout() only recurses through nested sizers, but once it
> hits a wx.Panel it does not automatically layout the sizer of that
> panel. So why should frame.Layout() have any effect on the innards of
> a nested wx.Panel subclass?
>
> Can someone explain why?

The layout of the parent will ask each of the children for their best
size, and for children that have their own sizers it will ask the sizer
for the min size needed for the layout. In this case that will trigger
an adjustment of the virtual size like my suggestion above.


--
Robin Dunn
Software Craftsman
http://wxPython.org

Anders J. Munch

unread,
Dec 19, 2013, 3:59:04 AM12/19/13
to wxpytho...@googlegroups.com
> Anders J. Munch wrote:
> > I had a ScrolledWindow problem: When showing and hiding content
> > programmatically in a GridBagSizer within the ScrolledWindow, the
> > scrollbar didn't update.
Robin:
> You need to adjust the virtual size of the scrolled window to the new
> needs of the sizer. Something like this:
>
> w, h = self.sizer.GetMinSize()
> self.SetVirtualSize( (w, h) )

Thanks; that works perfectly.

I've added my sample with small changes to
http://wiki.wxpython.org/ScrolledWindows

regards, Anders

Reply all
Reply to author
Forward
0 new messages