问题
Can a wx.PyControl
contain a wx.Sizer
?
Note that what I am ultimately trying to do here (spinner with float values) is already answered in another question. I am particularly interested in layouting widgets within a wx.PyControl
, a skill which might prove useful if I come across a need to make my own custom widgets. I already read through CreatingCustomControls, but it didn't use sizers within the wx.PyControl
subclass.
Using my code below, my CustomWidget
just doesn't look right. I'm not yet doing a DoGetBestSize
because I think that applies to a wx.Sizer
acting on a widget. I am actually having a wx.Sizer
doing its thing inside a CustomWidget
.
Here is my code (without the event bindings between sub-widgets):
EDIT: Here is my corrected class code, thanks to Steven Sproat:
import wx
class CustomWidget(wx.PyControl):
def __init__(self, parent):
wx.PyControl.__init__(self, parent=parent, style=wx.NO_BORDER) # Style added.
text = wx.TextCtrl(parent=self)
spin = wx.SpinButton(parent=self, style=wx.SP_VERTICAL)
sizer = wx.GridBagSizer()
self.layout(text, spin, sizer)
self.OnInit(text, sizer)
def OnInit(self, text, sizer):
text.SetValue(u"0.000")
def layout(self, text, spin, sizer):
self.SetSizer(sizer)
sizer.Add(text, pos=(0, 0), flag=wx.ALIGN_CENTER)
sizer.Add(spin, pos=(0, 1), flag=wx.ALIGN_CENTER)
self.Fit()
self.Layout() # This is what I lacked. I needed to call .Layout()
self.CenterOnParent()
回答1:
Yes, it can. You just need to call Layout() to tell the sizer to recalculate/layout its children.
import wx
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
blah = CustomWidget(self)
self.Show(True)
class CustomWidget(wx.PyControl):
def __init__(self, parent):
wx.PyControl.__init__(self, parent=parent)
text = wx.TextCtrl(parent=self)
spin = wx.SpinButton(parent=self, style=wx.SP_VERTICAL)
sizer = wx.GridBagSizer()
self.layout(text, spin, sizer)
self.OnInit(text, sizer)
def OnInit(self, text, sizer):
text.SetValue(u"0.000")
def layout(self, text, spin, sizer):
self.SetSizer(sizer)
sizer.Add(text, pos=(0, 0), flag=wx.ALIGN_CENTER)
sizer.Add(spin, pos=(0, 1), flag=wx.ALIGN_CENTER)
self.Fit()
self.Layout()
self.CenterOnParent()
app = wx.App()
f = Frame()
app.MainLoop()
By the way, it would be nice in the future if you could attach a runnable sample as above :)
回答2:
Since classes derived from wxControl are not normally used for containing other widgets the auto-layout code is not present and so it will not call Layout() when it gets the EVT_SIZE event. You can easily add that ability to your class by Bind()ing a handler for EVT_SIZE and calling self.Layout() from there. Then it will act just like a panel does when it gets the size event and has children and a sizer.
来源:https://stackoverflow.com/questions/3271639/wxpython-can-a-wx-pycontrol-contain-a-wx-sizer