wxpython 将变量传递给回调事件。Lambda地带
我是不是对lambda表达式理解错了?还是说我想传递的变量GetValue()
是空的?这样的话,直接创建一个global palletNumberText
会不会更好呢?在createWidgets()
里,我绑定了一个EVT_TEXT
事件,这样当在TextCtrl
里输入文本时,就会调用onPalletNumberText(event, variable_here)
这个函数。
我在以下这行代码上遇到了困难:
palletNumberText.Bind(wx.EVT_TEXT, lambda event, temp_str=palletNumberText.GetValue(): self.onPalletNumberText( event, temp_str ))
在这个代码片段里:
class ClassName(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title)
self.panel = wx.Panel(self)
self.PhotoMaxSize = 240
self.createWidgets()
self.Show()
def createWidgets(self):
.
.
.
palletNumberText = wx.TextCtrl(self.panel, size=(80,-1))
# THIS LINE
palletNumberText.Bind(wx.EVT_TEXT, lambda event, temp_str=palletNumberText.GetValue(): self.onPalletNumberText( event, temp_str ))
.
.
.
def onPalletNumberText(self, event, palletNumber):
'''
save palletNumbertTxt Value when text is entered
'''
print palletNumber
print "This is a test"
# Store Value
return
我查阅了一些资料:
- wxpython,如何将数据传递给self.Bind中的函数
- http://wiki.wxpython.org/Passing%20Arguments%20to%20Callbacks
- wxpython 传递信息和指针?
- 我该如何将变量传递给事件处理器?
- 可以将参数传递给事件绑定吗?
- http://wxpython-users.1045709.n5.nabble.com/GetValue-from-TextCtrl-by-hitting-a-button-td3203210.html
- 从TextCtrl框中获取字符串
不过我的结果是:
谢谢。
3 个回答
问题确实出在你提到的那一行代码上。问题在于,temp_str
的默认值是在调用Bind
方法时计算的,而不是在事件触发时计算的。当你绑定事件时,palletNumberText
字段是空的,因为你刚刚创建了这个palletNumberText
控件。
这一行代码的效果和下面这两行是一样的:
default_value = palletNumberText.GetValue() # will always be "", you've only just created it
palletNumberText.Bind(wx.EVT_TEXT, lambda event, temp_str=default_value: self.onPalletNumberText( event, temp_str ))
解决这个问题的一种方法是把palletNumberText.GetValue()
的调用放到一个lambda表达式的内部,并为temp_str
参数使用一个默认值,比如None
:
palletNumberText.Bind(wx.EVT_TEXT, lambda event, temp_str=None: self.onPalletNumberText( event, palletNumberText.GetValue() if temp_str is None else temp_str ))
不过,这一行代码变得比较长,可能更好的是创建一个函数,而不是试图把太多代码塞进一个lambda表达式里。另一种选择是把palletNumberText
作为你的ClassName
类的一个属性,然后让self.onPalletNumberText
方法检查它的内容。
你的默认参数是在程序开始时就被计算的
lambda event, temp_str=None: self.onPalletNumberText( event,
temp_str if temp_str is not None else palletNumberText.GetValue() )
我觉得这样可以工作
但你真正想要的可能更像是
lambda event, txt_instance=palletNumberText: self.onPalletNumberText( event, txt_instance.GetValue() )
问题在于你在你的lambda表达式里面调用了GetValue方法。这样做会立即执行,也就是说它会在文本控件还没显示出来之前就获取值。换句话说,它获取的值总是空的。这个方法并不是每次事件触发时都会被调用。
相反,你应该直接在事件处理函数里面调用GetValue():
import wx
class ClassName(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title)
self.panel = wx.Panel(self)
self.PhotoMaxSize = 240
self.createWidgets()
self.Show()
def createWidgets(self):
self.palletNumberText = wx.TextCtrl(self.panel, size=(80,-1))
self.palletNumberText.Bind(wx.EVT_TEXT, self.onPalletNumberText)
def onPalletNumberText(self, event):
'''
save palletNumbertTxt Value when text is entered
'''
print self.palletNumberText.GetValue()
print "This is a test"
# Store Value
return
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = ClassName(None, "Test")
app.MainLoop()