Reputation: 413
The following wxPython sample code is meant to create some buttons and then add them to a horizontal panel in such a way that the buttons should flow to a new row when they no longer fit in the panel.
In addition, the buttons should change position (increase/decrease the number of rows) as the user resizes the frame/window. (please see http://wxpython-users.1045709.n5.nabble.com/Button-wrap-td2365760.html).
import wx
words = ['lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur',
'adipisicing', 'elit', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt',
'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua', 'ut', 'enim', 'ad',
'minim', 'veniam', 'quis', 'nostrud', 'exercitation', 'ullamco',
'laboris', 'nisi', 'ut', 'aliquip', 'ex', 'ea', 'commodo',
'consequat', 'duis', 'aute', 'irure', 'dolor', 'in', 'reprehenderit',
'in', 'voluptate', 'velit', 'esse', 'cillum', 'dolore', 'eu',
'fugiat', 'nulla', 'pariatur', 'excepteur', 'sint', 'occaecat',
'cupidatat', 'non', 'proident', 'sunt', 'in', 'culpa', 'qui',
'officia', 'deserunt', 'mollit', 'anim', 'id', 'est', 'laborum']
class Example(wx.Frame):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.InitUI()
self.Ctrls()
i = 0
for word in words:
i += 1
print " word = ",word, " ",i
self.gridSizer.SetCols(5)
button = wx.Button(self.panel, -1, word, size=wx.Size(70,25))
self.gridSizer.Add(button, 1, wx.EXPAND)
self.panel.Layout()
def InitUI(self):
self.SetSize((800, 400))
self.SetTitle('Dynamically Flow Buttons to Next Row on Window-Resize')
self.Centre()
self.Show(True)
def Sizers(self):
self.gridSizer = wx.GridSizer(cols=0, hgap=1, rows=1, vgap=1)
self.panel.SetSizer(self.gridSizer)
def Ctrls(self):
self.Bind(wx.EVT_SIZE, self.OnFrameSize)
self.panel = wx.Panel(parent=self,pos=wx.Point(0,0), size=wx.Size(750,550), style=wx.TAB_TRAVERSAL)
self.Sizers()
def OnFrameSize(self, event):
self.UpdateButtonLayout()
event.Skip()
def UpdateButtonLayout(self):
panelwidth = self.panel.GetSize().width
print panelwidth
factor = panelwidth / 70
print "Factor: ", factor
self.gridSizer.SetCols(factor)
self.panel.Layout()
def main():
ex = wx.App()
Example(None)
ex.MainLoop()
if __name__ == '__main__':
main()
When I run this example I get the following error;
Traceback (most recent call last):
File "test.py", line 68, in <module>
main()
File "test.py", line 64, in main
Example(None)
File "test.py", line 26, in __init__
self.gridSizer.Add(button, 1, wx.EXPAND)
File "/usr/local/lib/wxPython-3.0.2.0/lib/python2.7/site-packages/wx-3.0-osx_cocoa/wx/_core.py", line 14457, in Add
return _core_.Sizer_Add(*args, **kwargs)
wx._core.PyAssertionError: C++ assertion "Assert failure" failed at /BUILD/wxPython-src-3.0.2.0/src/common/sizer.cpp(1401) in DoInsert(): too many items (6 > 5*1) in grid sizer (maybe you should omit the number of either rows or columns?)
The problem is with line number 26. When I comment that out I see only a single button. Can someone suggest some changes to make it work? Thanks.
Upvotes: 0
Views: 716
Reputation: 22458
A late answer but using a FlexGridSizer
would achieve the same result, where the number of rows is set to zero.
In the questions code, you would also have to delete the line self.gridSizer.SetCols(5)
import wx
words = ['lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur',
'adipisicing', 'elit', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt',
'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua', 'ut', 'enim', 'ad',
'minim', 'veniam', 'quis', 'nostrud', 'exercitation', 'ullamco',
'laboris', 'nisi', 'ut', 'aliquip', 'ex', 'ea', 'commodo',
'consequat', 'duis', 'aute', 'irure', 'dolor', 'in', 'reprehenderit',
'in', 'voluptate', 'velit', 'esse', 'cillum', 'dolore', 'eu',
'fugiat', 'nulla', 'pariatur', 'excepteur', 'sint', 'occaecat',
'cupidatat', 'non', 'proident', 'sunt', 'in', 'culpa', 'qui',
'officia', 'deserunt', 'mollit', 'anim', 'id', 'est', 'laborum']
class Example(wx.Frame):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.InitUI()
self.Ctrls()
i = 0
for word in words:
i += 1
print " word = ",word, " ",i
button = wx.Button(self.panel, -1, word, size=wx.Size(70,25))
self.gridSizer.Add(button, 1, wx.EXPAND)
self.panel.Layout()
def InitUI(self):
self.SetSize((800, 400))
self.SetTitle('Dynamically Flow Buttons to Next Row on Window-Resize')
self.Centre()
self.Show(True)
def Sizers(self):
self.gridSizer = wx.FlexGridSizer(0,5,1,1)
self.panel.SetSizer(self.gridSizer)
def Ctrls(self):
self.Bind(wx.EVT_SIZE, self.OnFrameSize)
self.panel = wx.Panel(parent=self,pos=wx.Point(0,0), size=wx.Size(750,550), style=wx.TAB_TRAVERSAL)
self.Sizers()
def OnFrameSize(self, event):
self.UpdateButtonLayout()
event.Skip()
def UpdateButtonLayout(self):
panelwidth = self.panel.GetSize().width
print panelwidth
factor = panelwidth / 70
print "Factor: ", factor
self.gridSizer.SetCols(factor)
self.panel.Layout()
def main():
ex = wx.App()
Example(None)
ex.MainLoop()
if __name__ == '__main__':
main()
Upvotes: 0
Reputation: 33111
What you are looking for is the wx.WrapSizer
. I updated your code a bit to use it instead:
import wx
words = ['lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur',
'adipisicing', 'elit', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt',
'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua', 'ut', 'enim', 'ad',
'minim', 'veniam', 'quis', 'nostrud', 'exercitation', 'ullamco',
'laboris', 'nisi', 'ut', 'aliquip', 'ex', 'ea', 'commodo',
'consequat', 'duis', 'aute', 'irure', 'dolor', 'in', 'reprehenderit',
'in', 'voluptate', 'velit', 'esse', 'cillum', 'dolore', 'eu',
'fugiat', 'nulla', 'pariatur', 'excepteur', 'sint', 'occaecat',
'cupidatat', 'non', 'proident', 'sunt', 'in', 'culpa', 'qui',
'officia', 'deserunt', 'mollit', 'anim', 'id', 'est', 'laborum']
class Example(wx.Frame):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.InitUI()
self.Ctrls()
i = 0
for word in words:
i += 1
print " word = ",word, " ",i
button = wx.Button(self.panel, -1, word, size=wx.Size(70,25))
self.wrapSizer.Add(button, 1, wx.EXPAND)
self.Show(True)
self.panel.Layout()
def InitUI(self):
self.SetSize((800, 400))
self.SetTitle('Dynamically Flow Buttons to Next Row on Window-Resize')
self.Centre()
def Sizers(self):
self.wrapSizer = wx.WrapSizer()
self.panel.SetSizer(self.wrapSizer)
def Ctrls(self):
self.panel = wx.Panel(parent=self,pos=wx.Point(0,0), size=wx.Size(750,550), style=wx.TAB_TRAVERSAL)
self.Sizers()
def main():
ex = wx.App()
Example(None)
ex.MainLoop()
if __name__ == '__main__':
main()
Note that you cannot set the number of columns. You can read more about this fun widget at the following:
Upvotes: 1