I have a follow up question to this thread: Hiding scroll bars causes rendering to change (Possible bug?)
For my case, I have a ScrolledWindow with buttons where I hide the ScrollBars. I have 2 buttons to scroll left and right.
komoto48g gave an excellent answer and example for updating the client area of the ScrolledWindow after scrolling. Now I am able to scroll in either direction.
However, when I re-size the window, the child buttons’ layout does not update correctly.
Follow these steps to re-create the issue:
- Scroll to the right (sizer is no longer at position 0)
- Re-size the window (child buttons to the right are re-drawn on top of others)
No issue scrolling right:
Issue after window re-size:
I can’t figure out how or where to update the ScrolledWindow’s layout to avoid this. Maybe in a size event handler?
You will notice that I have bound each button to a size event where they are “re-fitted”. This avoids them looking squished when the window is shrunk.
import wx
class AppWindow(wx.Frame):
def __init__(self, parent, title):
super(AppWindow, self).__init__(parent=parent, title=title, size=(350, 200))
# Sizer for the frame
frame_sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(frame_sizer)
# Scrolled window for the buttons
self.scrolled_win = wx.ScrolledWindow(parent=self)
frame_sizer.Add(self.scrolled_win, proportion=1, flag=wx.EXPAND)
self.sizer_scrolled_win = wx.BoxSizer(orient=wx.HORIZONTAL)
self.scrolled_win.SetSizer(sizer=self.sizer_scrolled_win)
# Add Buttons
for i in range(1, 8):
btn = wx.Button(parent=self.scrolled_win, label="Button %s" % i)
self.sizer_scrolled_win.Add(btn, proportion=1, flag=wx.ALL, border=5)
btn.Bind(event=wx.EVT_SIZE, handler=self.__on_size_btn)
# Setup Scrollbars (hidden)
self.scrolled_win.SetScrollbars(pixelsPerUnitX=10, pixelsPerUnitY=0, noUnitsX=10, noUnitsY=0,
xPos=0, yPos=0, noRefresh=False)
self.scrolled_win.ShowScrollbars(horz=wx.SHOW_SB_NEVER, vert=wx.SHOW_SB_NEVER)
# Scroll Buttons
# - Sizer
sizer_scroll_btns = wx.BoxSizer(orient=wx.HORIZONTAL)
frame_sizer.Add(sizer_scroll_btns, proportion=0, flag=wx.EXPAND)
# - Scroll Left
scroll_left = wx.Button(parent=self, label="< Left", name='scroll_left')
sizer_scroll_btns.Add(scroll_left, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
scroll_left.Bind(event=wx.EVT_BUTTON, handler=self.__on_button)
# - Scroll Right
scroll_right = wx.Button(parent=self, label="Right >", name='scroll_right')
sizer_scroll_btns.Add(scroll_right, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
scroll_right.Bind(event=wx.EVT_BUTTON, handler=self.__on_button)
self.Show()
def __on_button(self, event):
x, y = self.scrolled_win.GetViewStart()
if event.EventObject.GetName() == 'scroll_right':
# Scroll buttons right
self.scrolled_win.Scroll(x=x+10, y=0)
elif event.EventObject.GetName() == 'scroll_left':
# Scroll buttons left
self.scrolled_win.Scroll(x=x-10, y=0)
# Send size event and update sizer dimension to refresh the scrolled window client area
self.scrolled_win.SendSizeEvent()
self.sizer_scrolled_win.SetDimension(pos=self.sizer_scrolled_win.Position,
size=self.sizer_scrolled_win.MinSize)
event.Skip()
def __on_size_btn(self, event):
# Keeps the buttons from being "squished" on re-size
event.EventObject.Fit()
event.Skip()
if __name__ == '__main__':
app = wx.App(False)
frame = AppWindow(None, "Test")
app.MainLoop()