Hi guys,
I'm having a lot of trouble getting my wxGridSizer to work properly in my
application. It works fine under Linux, but as soon as I try to run my program
under Windows, the wxGridSizer seems to go haywire.
My program is using a wxGridSizer to lay out a number of "Job Lists"
(basically a wxPanel containing a heading and a wxGrid) into a matrix-like
pattern in the window. When the window is resized, the number of lists which
will fit across the window is recalculated, and a new wxGridSizer is created
with that number of columns (there doesn't seem to be any way of dynamically
changing the number of rows and/or columns for a wxGridSizer, so I have to
create a new one from scratch), and then all the lists are created and added to
the wxGridSizer in order. The result is that the window shows as many lists
across as the window will fit, but will use a vertical scrollbar if there are
more lists than can be shown in the window at one time.
My program allows for job lists to be created and removed on the fly -- each
time a list is created or removed, I'm calling my rebuild() routine to recreate
all the remaining lists and lay them out again, so that no holes are left as
the job lists are laid out in the window.
Anyway, as I say all this works beautifully under Linux, but for some reason
wxGridSizer seems to misbehave when running under Windows. Below is a
simplified program which shows up the problem -- try clicking on "Add" several
times in succession. Under Linux, each call to doAdd() causes the window to be
laid out correctly. Under Windows, the items are all laid out one on top of
the other, and only occasionally do they lay out correctly. The same thing
happens when you try to resize the window...
It's quite interesting to compare the behaviour under Linux and Windows --
they're quite different! Can anyone suggest a workaround for getting my
wxGridSizer to work properly under Windows? I'm quite desperate to get this
fixed, as my program *needs* to run under Windows and with this layout logic
broken my entire program is unusable -- and I've got people waiting to test it.
I'd be *really* grateful if someone could help me figure out how to fix this...
Thanks in advance,
- Erik.
#--------- Python Code Follows ----------------------------------------------
from wxPython.wx import *
import whrandom
class TestFrame(wxFrame):
def __init__(self, parent, id, title):
wxFrame.__init__(self, parent, id, title)
self.SetAutoLayout(true)
btnPanel = wxPanel(self, -1)
btnSizer = wxBoxSizer(wxVERTICAL)
btnAdd = wxButton(btnPanel, 1001, "Add")
btnRemove = wxButton(btnPanel, 1002, "Remove")
btnSizer.Add(btnAdd, 0, wxALL, 5)
btnSizer.Add(btnRemove, 0, wxALL, 5)
btnPanel.SetAutoLayout(true)
btnPanel.SetSizer(btnSizer)
btnSizer.Fit(btnPanel)
EVT_BUTTON(self, 1001, self.doAdd)
EVT_BUTTON(self, 1002, self.doRemove)
self.scroller = wxScrolledWindow(self, -1)
self.scroller.SetAutoLayout(true)
self.scroller.EnableScrolling(false, true)
self.panel = wxPanel(self.scroller, -1)
self.panel.SetAutoLayout(true)
self.sizer = None
topSizer = wxBoxSizer(wxHORIZONTAL)
topSizer.Add(btnPanel, 0, wxALL, 5)
topSizer.Add(self.scroller, 1, wxEXPAND | wxALL, 5)
self.SetAutoLayout(true)
self.SetSizer(topSizer)
self.SetSizeHints(minW=100, minH=200)
self.SetSize(wxSize(600, 400))
EVT_SIZE(self, self.OnSizeWindow)
self.items = {}
self.rebuild()
def doAdd(self, event):
itemNum = len(self.items.keys()) + 1
self.items[itemNum] = None
self.rebuild()
def doRemove(self, event):
if len(self.items.keys()) > 0:
keys = self.items.keys()
itemNum = self.items.keys()[whrandom.randint(0, len(keys)-1)]
if self.items[itemNum] != None: self.items[itemNum].Destroy()
del self.items[itemNum]
self.rebuild()
def rebuild(self):
for itemNum in self.items.keys():
item = self.items[itemNum]
if item != None:
item.Destroy()
self.items[itemNum] = None
self.scroller.Scroll(0, 0)
self.sizer = None
items = self.items.keys()
items.sort()
for itemNum in items:
item = wxButton(self.panel, -1, str(itemNum))
item.SetSize(wxSize(100, 50))
item.SetSizeHints(100, 50)
if self.sizer == None:
itemWidth = item.GetSize().width
totWidth = self.scroller.GetClientSize().width
numCols = totWidth / (itemWidth + 10)
if numCols < 1: numCols = 1
self.sizer = wxGridSizer(0, numCols, 10, 10)
self.sizer.Add(item, 0, wxALIGN_TOP)
self.items[itemNum] = item
if self.sizer != None:
self.panel.SetSizer(self.sizer)
self.sizer.Fit(self.panel)
height = self.panel.GetSize().height
self.scroller.SetScrollbars(20, 20, 0, (height + 20) / 20)
def OnSizeWindow(self, event):
event.Skip()
self.rebuild()
class TestApp(wxApp):
def OnInit(self):
frame = TestFrame(NULL, -1, "Test")
self.SetTopWindow(frame)
frame.Show(TRUE)
return TRUE
# Main program:
app = TestApp(0)
app.MainLoop()