patternpythonMinor
wxPython Form Builder - Sizer Automation
Viewed 0 times
builderwxpythonautomationsizerform
Problem
Presented for critique are a pair of classes which automate Sizer Creation and Layout in wxPython.
```
import wx
from wx.lib.combotreebox import ComboTreeBox
from wx.lib.agw.floatspin import FloatSpin
wx.ComboTreeBox = ComboTreeBox
wx.FloatSpin = FloatSpin
class FormDialog(wx.Dialog):
def __init__(self, parent, id = -1, panel = None, title = "Unnamed Dialog",
modal = False, sizes = (-1, -1), refid = None):
wx.Dialog.__init__(self, parent, id, title,
style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
if panel is not None:
self._panel = panel(self, refid)
self._panel.SetSizeHints(*sizes)
ds = wx.GridBagSizer(self._panel._gap, self._panel._gap)
ds.Add(self._panel, (0, 0), (1, 1), wx.EXPAND | wx.ALL, self._panel._gap)
ds.Add(wx.StaticLine(self), (1, 0), (1, 1), wx.EXPAND | wx.RIGHT | wx.LEFT, self._panel._gap)
self.bs = self.CreateButtonSizer(self._panel._form.get('Buttons', wx.OK | wx.CANCEL))
ds.Add(self.bs, (2, 0), (1, 1), wx.ALIGN_RIGHT | wx.ALL, self._panel._gap)
ds.AddGrowableCol(0)
ds.AddGrowableRow(0)
self.SetSizerAndFit(ds)
self.Center()
self.Bind(wx.EVT_BUTTON, self._panel.onOk, id = wx.ID_OK)
self.Bind(wx.EVT_BUTTON, self._panel.onClose, id = wx.ID_CANCEL)
focused = self._panel._form.pop('Focus', None)
if focused:
self._panel.itemMap[focused].SetFocus()
if modal:
self.ShowModal()
else:
self.Show()
class Form(wx.Panel):
def __init__(self, parent = None, refid = None, id = -1, gap = 3, sizes = (-1, -1)):
wx.Panel.__init__(self, parent, id)
self.SetSizeHints(*sizes)
self._gap = gap
self.itemMap = {}
self.refid = refid
if not hasattr(self, 'q'):
self.q = getattr(self.GrandParent, 'q', None)
if hasattr(self, '_form'):
# Before building verify that several required elements exist in the form
# definition object.
self
```
import wx
from wx.lib.combotreebox import ComboTreeBox
from wx.lib.agw.floatspin import FloatSpin
wx.ComboTreeBox = ComboTreeBox
wx.FloatSpin = FloatSpin
class FormDialog(wx.Dialog):
def __init__(self, parent, id = -1, panel = None, title = "Unnamed Dialog",
modal = False, sizes = (-1, -1), refid = None):
wx.Dialog.__init__(self, parent, id, title,
style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
if panel is not None:
self._panel = panel(self, refid)
self._panel.SetSizeHints(*sizes)
ds = wx.GridBagSizer(self._panel._gap, self._panel._gap)
ds.Add(self._panel, (0, 0), (1, 1), wx.EXPAND | wx.ALL, self._panel._gap)
ds.Add(wx.StaticLine(self), (1, 0), (1, 1), wx.EXPAND | wx.RIGHT | wx.LEFT, self._panel._gap)
self.bs = self.CreateButtonSizer(self._panel._form.get('Buttons', wx.OK | wx.CANCEL))
ds.Add(self.bs, (2, 0), (1, 1), wx.ALIGN_RIGHT | wx.ALL, self._panel._gap)
ds.AddGrowableCol(0)
ds.AddGrowableRow(0)
self.SetSizerAndFit(ds)
self.Center()
self.Bind(wx.EVT_BUTTON, self._panel.onOk, id = wx.ID_OK)
self.Bind(wx.EVT_BUTTON, self._panel.onClose, id = wx.ID_CANCEL)
focused = self._panel._form.pop('Focus', None)
if focused:
self._panel.itemMap[focused].SetFocus()
if modal:
self.ShowModal()
else:
self.Show()
class Form(wx.Panel):
def __init__(self, parent = None, refid = None, id = -1, gap = 3, sizes = (-1, -1)):
wx.Panel.__init__(self, parent, id)
self.SetSizeHints(*sizes)
self._gap = gap
self.itemMap = {}
self.refid = refid
if not hasattr(self, 'q'):
self.q = getattr(self.GrandParent, 'q', None)
if hasattr(self, '_form'):
# Before building verify that several required elements exist in the form
# definition object.
self
Solution
wx.ComboTreeBox = ComboTreeBox
wx.FloatSpin = FloatSpinModifying the contents of another module is suspicious and likely to cause trouble. Your changes might not be there when another module is importing and could cause trouble.
ds = wx.GridBagSizer(self._panel._gap, self._panel._gap)
ds.Add(self._panel, (0, 0), (1, 1), wx.EXPAND | wx.ALL, self._panel._gap)
ds.Add(wx.StaticLine(self), (1, 0), (1, 1), wx.EXPAND | wx.RIGHT | wx.LEFT, self._panel._gap)
self.bs = self.CreateButtonSizer(self._panel._form.get('Buttons', wx.OK | wx.CANCEL))Empty lines can be used to put related statements together. The benefit is lost when you do it for every statement.
focused = self._panel._form.pop('Focus', None)The _ in _form indicates that its for the internal use of the panel. So why are you accessing it here?
if not hasattr(self, 'q'):
self.q = getattr(self.GrandParent, 'q', None)What the fried monkey is q? It probably need a better name.
class GeneralSettings(Form):
def __init__(self, parent, refid = None):
self._form = {Perhaps form should be a class attribute rather then an attribute. Then you don't have a define a constructor in this class whatsoever.
'Parts': OD([OD?
('Log Settings', [
({'type': 'StaticText', 'label': 'Remove messages after'},
{'type': 'FloatSpin', 'name': 'interval', 'min_val': 1, 'max_val': 10, 'digits': 2, 'increment': 0.1, 'size': (55, -1), 'flags': wx.LEFT | wx.RIGHT},Instead of dictionaries, how about objects?
widgets.StaticText(label='Remove messages after'),
widgets.ComboBox(name='unit', flags = wx.LEFT | wx.RIGHT, style = wx.CBREADONLY)Then you can call methods on these objects to do all the work you are doing above. That way you can move all the widget specific data out of it. It should also make it easier to extend your system with new widgets. The system could also be extended to support things like OptionalSection, etc.
'Defaults': {
'interval': 3,
'log-level': 'Low',
'req-admin': False,
'unit': 'Days',
'printtasks': 5,
'jobdrop': 'Copy Job to Queue'
}These are being defined far away from the rest of the widget. Why?
You seem to comparing the ease of use of this versus manually writing the code. However, if I compare it to the use of a gui builder its not clear that its helpful. i.e. all the code that you are saving is already written for me by the builder tool and so it just isn't helpful on that front.
Code Snippets
wx.ComboTreeBox = ComboTreeBox
wx.FloatSpin = FloatSpinds = wx.GridBagSizer(self._panel._gap, self._panel._gap)
ds.Add(self._panel, (0, 0), (1, 1), wx.EXPAND | wx.ALL, self._panel._gap)
ds.Add(wx.StaticLine(self), (1, 0), (1, 1), wx.EXPAND | wx.RIGHT | wx.LEFT, self._panel._gap)
self.bs = self.CreateButtonSizer(self._panel._form.get('Buttons', wx.OK | wx.CANCEL))focused = self._panel._form.pop('Focus', None)if not hasattr(self, 'q'):
self.q = getattr(self.GrandParent, 'q', None)class GeneralSettings(Form):
def __init__(self, parent, refid = None):
self._form = {Context
StackExchange Code Review Q#3989, answer score: 2
Revisions (0)
No revisions yet.