这是我在StackOverFlow上的第一个问题。
Python版本:3.6.1,wxPython版本:4.0.1,操作系统:Windows 10,64位。
我一直在为一个科学项目探索wxPython。我需要动态生成滑块。这个我可以和StaticText元素一起显示第x个滑块位置的当前值。我有一个函数“CreateSliderFun”,它返回一个处理函数。我将xth处理函数绑定到第x个滑块小部件。我希望一切都很好,但会发生类型错误:
TypeError: fun() missing 1 required positional argument: 'e'
如果我提供hardcoded_fun,则第一个添加的滑块按预期工作。任何额外的滑块都将链接到第一个生成的StaticText元素。
import wx
def main():
app = wx.App(redirect=False)
frame = MyApp(None, 'Hello World!')
frame.Show(True)
app.MainLoop()
class MyApp(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, pos=(0,0), size=(400,600))
self.panel = wx.Panel(self, pos=(0,0), size=wx.Size(400,600))
self.AddSliderButton = wx.Button(self.panel, -1, "AddSlider", size=(80,20), pos=(120,80))
self.AddSliderButton.Bind(wx.EVT_BUTTON, self.AddSliderHandler)
self.sld = wx.Slider(self.panel, value=200,
minValue=200-100,
maxValue=200+100,
pos=(60, 10),
size=(250, -1), style=wx.SL_HORIZONTAL)
self.txt = wx.StaticText(self.panel, label='200', pos=(20, 10))
self.sld.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
self.AddSliderButton = wx.Button(self.panel, -1, "AddSlider", size=(80,20), pos=(120,80))
self.AddSliderButton.Bind(wx.EVT_BUTTON, self.AddSliderHandler)
self.statusbar = self.CreateStatusBar()
self.statusbar.SetStatusText("Moin")
self.ms = ManySliders(self.panel)
def OnSliderScroll(self, e):
obj = e.GetEventObject()
val = obj.GetValue()
self.txt.SetLabel(str(val))
def AddSliderHandler(self, event):
self.ms.AddSlider()
self.statusbar.SetStatusText("Added slider number " + str(self.ms.NumberOfSliders))
class ManySliders:
def __init__(self, controlpanel ):
self.controlpanel = controlpanel
self.txts = []
self.sliders = []
self.SliderFun = []
self.size = (250, -1)
self.style = wx.SL_HORIZONTAL
self.NumberOfSliders = 0
def AddSlider(self):
i = self.NumberOfSliders
txt = wx.StaticText(self.controlpanel, label=str(self.NumberOfSliders), pos=(20, 120 + i*20))
self.txts.append(txt)
sld = wx.Slider(self.controlpanel, value=self.NumberOfSliders,
minValue=self.NumberOfSliders-100,
maxValue=self.NumberOfSliders+100,
pos=(60, 120+i*20),
size=self.size, style=self.style)
self.sliders.append(sld)
sliderfun = self.CreateSliderFun(self.NumberOfSliders)
self.SliderFun.append(sliderfun)
self.sliders[i].Bind(wx.EVT_SCROLL, self.SliderFun[i])
self.NumberOfSliders += 1
def hardcoded_fun(self, e):
""" if self.SliderFun[i] is replaced by hardcoded_fun, the first added slider will work,
and all extra sliders added will be linked to the first created StaticText element
"""
obj = e.GetEventObject()
val = obj.GetValue()
self.txts[0].SetLabel(str(val))
def CreateSliderFun(self, i):
def fun(self, e):
print("but this is never shown due to TypeError: fun() missing 1 required positional argument: 'e'")
obj = e.GetEventObject()
val = obj.GetValue()
self.txts[i].SetLabel(str(val))
print("we create a new slider function... =",fun)
return fun
main()
答案 0 :(得分:1)
您的CreateSliderFun返回一个函数,该函数有2个参数:self和e。你需要这个:
def CreateSliderFun(self, i):
def fun(e):
....
你可以考虑不动态处理,而是做
self.Bind(wx.EVT_SCROLL, self.common_handler)
和
def common_handler(self, event):
source = event.GetEventObject() # this is your slider
txt_widget = self.txts[self.sliders.index(source)]
# I did not test it but you get the idea, right?