Reputation: 12304
SSCCE is at the bottom
My layout has two wx.ListBox
es, side-by side in a wx.FlexGridSizer
:
My real layout is more complex, thus the FGS, but this small example still exhibits the problem.
As you can see above, I have successfully used style = wx.LB_HSCROLL
to make each listbox use a horizontal scroll bar when one of its elements would make it too large to fit in the wx.Frame
.
However, as I resize the window smaller and smaller, eventually some critical point is reached, the first listbox decides it doesn't want to use its scrollbar anymore, and instead expands to its full size, pushing the second box to the right:
The point at which the list goes crazy depends on how long the string is. If I put a long enough string in the first box, then the above process is reversed: the layout starts off wrong and I have to resize the window up to the critical point, where all of a sudden the listbox starts using its scrollbar, gets a lot smaller, and the window becomes split down the middle as it should be.
I'm not sure if this is a bug in wxWidgets/wxPython or if I'm doing something wrong, but it's frustrating either way. Here is the simplest code I can come up with that shows the problem:
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent = None, size = (640, 480))
self.list1 = wx.ListBox(self, style = wx.LB_HSCROLL)
self.list2 = wx.ListBox(self, style = wx.LB_HSCROLL)
self.list1.Append('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
self.list2.Append('bbbbbbbbbbb')
self.fgs = wx.FlexGridSizer(1, 2)
self.fgs.AddMany([(self.list1, 1, wx.EXPAND), (self.list2, 1, wx.EXPAND)])
self.fgs.AddGrowableRow(0, 1)
self.fgs.AddGrowableCol(0, 1)
self.fgs.AddGrowableCol(1, 1)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Sizer = fgs
self.Layout()
self.Show()
def Exit(self, event):
self.Close(True)
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
EDIT: Here is my implementation of ravenspoint's code in python (code above was changed slightly to support this):
def OnSize(self, event):
if not self.list1 or not self.list2;
return
clientRect = self.GetClientRect()
min = wx.Size(clientRect.width / 2, clientRect.height)
self.list1.MinSize = min
self.list2.MinSize = min
Upvotes: 2
Views: 993
Reputation: 131
Since I ran into this problem as well, I'll post this for future reference. At least with wxPython, you must specify a min size or it will use the best size (at least for list boxes) and the sizer could possibly shove widgets outside of the current window frame. Thus, the added code to get the above code working as desired is:
self.list1.SetMinSize((10,10));
self.list2.SetMinSize((10,10));
The total working answer is:
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent = None, size = (640, 480))
self.list1 = wx.ListBox(self, style = wx.LB_HSCROLL)
self.list2 = wx.ListBox(self, style = wx.LB_HSCROLL)
self.list1.Append('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
self.list2.Append('bbbbbbbbbbb')
self.fgs = wx.FlexGridSizer(1, 2)
self.fgs.AddMany([(self.list1, 1, wx.EXPAND), (self.list2, 1, wx.EXPAND)])
self.fgs.AddGrowableRow(0, 1)
self.fgs.AddGrowableCol(0, 1)
self.fgs.AddGrowableCol(1, 1)
# Don't forget these two lines to allow for correct
# expansion/contraction of the sizer!
self.list1.SetMinSize((10,10));
self.list2.SetMinSize((10,10));
self.Sizer = self.fgs
self.Layout()
self.Show()
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
Upvotes: 1
Reputation: 20616
You may have to look after handling the resize event yourself. In C++ the handler would look something like this:
void MyFrame::OnSize(wxSizeEvent& )
{
if( ! ( list1 && list2 ) )
return;
wxRect frame_client = GetClientRect();
wxSize min(frame_client.width/2,frame_client.height );
list1->SetMinSize(min);
list2->SetMinSize(min);
fgs->Layout();
}
Upvotes: 1