Hi Mike Driscoll,
When you load new content or modify your GUI by adding or deleting
widgets, it's usually a good idea to call the frame's Layout() method
so that it recalculates the size of its children (and re-sizes
accordingly). This may need to be combined with a Refresh() too.
I experimented with both of them - but the problem remains the same.
I append the stripped-down code in the hope that this will help to
find the problem:
After starting the example code, a panel with 6 buttons is shown.
If you push on the button with the label '5', the 'items' page of
the notebook is filled with 5 buttons. As the page is to small to
show them all, scrollbars are shown. Both of the scrollbars don't
work...
When resizing the panel with the mouse, they finally work.
When clicking on the buttons the page is cleared and new items
are created. The scrollbars continue to work as long as there
are more items than fitting on the page. When button [0]
is pushed, all remaining items are destructed and
no scrollbars are shown any more. After recreating more than 2
items by pushing on button [5] for example, scrollbars are
shown again - but, as before, do not work. You can make them work
by manually resizing the frame with the mouse again...
Another way to create the same issue is by clicking on the buttons
in the notebook panel: clicking on button i will destruct item i...
When enough items are destructed to make the remaining ones
fit into the page again and then new items are recreated, the same
issue occurs...
Thanks for your help, Dietrich
Here comes the code:
---begin---
#!/usr/bin/env python
import os, sys
import wx
## =========================================================
class ItemPanel(wx.Panel):
def __init__(self, parent, settings, i):
wx.Panel.__init__(self, parent, wx.ID_ANY)
self.settings = settings
self.parent = parent
# sizer
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
self.sizer = sizer
# add a line
# !!! FIXME !!!: For some reason, when this line is not added, nothing is shown at all...
sizer.Add(wx.StaticLine(self, -1, size=(1024,-1)), 0, wx.ALL, 5)
# add a [Delete] button
button = wx.Button(self, -1, "%d" % i)
button.SetToolTipString("Delete this item")
self.Bind(wx.EVT_BUTTON, self.onDelete, button)
sizer.Add(button, 1, wx.SHAPED)
def onDelete(self, event):
self.parent.deleteItemPanel(self)
## =========================================================
class ItemListPanel(wx.Panel):
def __init__(self, parent, settings):
wx.Panel.__init__(self, parent, wx.ID_ANY)
self.settings = settings
self.parent = parent
# storage for item panels
self.itemPanels = {}
# sizer
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
self.sizer = sizer
# fit inside the scrolled window
self.parent.FitInside()
def deleteItemPanel(self, itemPanel):
# destroy the item panel
itemPanel.Destroy()
# delete from list of item panels
del self.itemPanels[itemPanel]
# fit inside the scrolled window
self.parent.FitInside()
def clear(self):
# destroy the item panels
for item in self.itemPanels.keys():
item.Destroy()
# clear the list with the destroyed item panels
self.itemPanels = {}
# fit inside the scrolled window
self.parent.FitInside()
def createItems(self, i):
# clear up from old items
self.clear()
# add the new items
for i in range(i):
itemPanel = ItemPanel(self, self.settings, i)
self.itemPanels[itemPanel] = i
self.sizer.Add(itemPanel, 0, wx.EXPAND)
# fit inside the scrolled window
self.parent.FitInside()
## =========================================================
class ButtonPanel(wx.Panel):
def __init__(self, parent, settings):
wx.Panel.__init__(self, parent, wx.ID_ANY)
self.parent = parent
self.settings = settings
# sizer
sizer = wx.BoxSizer(wx.HORIZONTAL)
self.SetSizer(sizer)
self.sizer = sizer
# add test buttons
self.testButtons = {}
for i in range(6):
# test button for i items
button = wx.Button(self, -1, "%d" % i)
# store button under its id
id = button.GetId()
self.testButtons[id] = i
self.Bind(wx.EVT_BUTTON, self.onTestButton, button)
sizer.Add(button, 0, wx.EXPAND)
# Layout button panel
self.SetAutoLayout(1)
def onTestButton(self, event):
# get number of items to create
id = event.GetId()
i = self.testButtons[id]
# create the items
self.settings['item-panel'].createItems(i)
## =========================================================
class ScrolledWindow(wx.ScrolledWindow):
def __init__(self, parent, settings):
wx.ScrolledWindow.__init__(self, parent, -1, (0, 0), size = wx.DefaultSize, style = wx.SUNKEN_BORDER)
self.parent = parent
self.settings = settings
# sizer
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
self.sizer = sizer
# scroll rate
self.SetScrollRate(20,20)
# add item panel
panel = ItemListPanel(self, settings)
settings['item-panel'] = panel
sizer.Add(panel, 0, wx.EXPAND)
## =========================================================
class Notebook(wx.Notebook):
def __init__(self, parent, settings):
wx.Notebook.__init__(self, parent, -1, size = (-1, 160), style = wx.BK_DEFAULT)
self.parent = parent
self.settings = settings
# add items panel page
panel = ScrolledWindow(self, settings)
self.addPage(panel, "Items")
def addPage(self, page, title):
def OnCPSize(evt, panel = page):
page.SetPosition((0, 0))
page.SetSize(evt.GetSize())
page.Bind(wx.EVT_SIZE, OnCPSize)
wx.Notebook.AddPage(self, page, title)
## =========================================================
class MainWindow(wx.Frame):
def __init__(self, parent, settings):
wx.Frame.__init__(self, parent, title = "Test", size = (-1, -1))
self.parent = parent
self.settings = settings
# sizer
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
self.sizer = sizer
# add item panel
self.notebookPanel = Notebook(self, settings)
sizer.Add(self.notebookPanel, 1, wx.EXPAND)
# Buttons from the button panel
self.buttonPanel = ButtonPanel(self, settings)
sizer.Add(self.buttonPanel, 0, wx.EXPAND)
# storing the main window in the settings
settings['main-window'] = self
# fit
self.SetAutoLayout(1)
sizer.Fit(self)
# Show the frame.
self.Show(True)
## =========================================================
## Main
## ---------------------------------------------------------
app = wx.App(False)
settings = {}
settings['main-window'] = MainWindow(None, settings)
app.MainLoop()
## =========================================================
## =========================================================
## fin.
---end---
-------------------
Mike Driscoll
Blog: http://blog.pythonlibrary.org
Thank you!
···
On Tue, 2010-03-16 at 06:12 -0700, Mike Driscoll wrote:
On Mar 15, 10:04 pm, Dietrich Bollmann <dir...@web.de> wrote:
> On Mon, 2010-03-15 at 12:15 -0700, Robin Dunn wrote:
> > On 3/15/10 2:05 AM, Dietrich Bollmann wrote:
> > > Hi,
>
> > > I made an instance of wx.Notebook with a page being an instance of
> > > wx.ScrolledWindow. In the scrolled window I add / delete some items.
> > > In order to resize the scrolled window I then call sizer.Fit(self). The
> > > panel is resized as expected - but when trying to use the scrollbars,
> > > they don't scroll the panel anymore. After resizing the main window
> > > (with my mouse) scrolling works again...
>
> > > Any idea?
>
> > When you call Fit then it is resizing the scrolled window to be large
> > enough to fit the content without needing to be scrolled, even if that
> > is larger than the client area of the notebook. When you tweak the size
> > then the notebook is resizing the scrolled window to fit the client area
> > again, meaning that it is smaller than the virtual size and so the
> > scrollbars will be active again. Try using scrolledWindow.FitInside()
> > instead.
>
> Thank you very much!
>
> Your advice helped a lot and the scrolled window works much better now!
>
> But when the pane inside the scrolled window gets so short, that the
> scrollbar on the side vanishes, and after some new content is loaded
> which makes the scrollbar appear again, the problem is there again.
>
> Resizing the window makes it work again as before. After resizing it
> works until the pane fits without the scrollbar again where I have to
> manually resize once more...
>
> As I start with an empty pane inside the scrolled window, initially
> (after starting the application) the problem is always there.
>
> Thanks, Dietrich
>