3

Am I not understanding something about lambdas? Or GetValue() the variable that I am trying to pass is empty. Is it best to just create a global palletNumberText for this? In createWidgets() I am binding an EVT_TEXT so that when text is entered into the TextCtrl it should call onPalletNumberText(event, variable_here)

The following line is where I am having difficulties:

palletNumberText.Bind(wx.EVT_TEXT, lambda event, temp_str=palletNumberText.GetValue(): self.onPalletNumberText( event, temp_str ))

Inside this Code Snippet:

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

Readings that I have looked at:

However my results:

results

Thanks.

1
  • Is there a reason you're using an optional argument in the lambda? Event-handler functions in wxPython are only ever called with the event, so the temp_str parameter will never be given a value by itself and will always have the default value. Commented Apr 4, 2014 at 21:12

3 Answers 3

3

your default argument is evaluated at start time

lambda event, temp_str=None: self.onPalletNumberText( event, 
                             temp_str if temp_str is not None else palletNumberText.GetValue() )

I think would work

but what you really want is probably something more like

lambda event, txt_instance=palletNumberText: self.onPalletNumberText( event, txt_instance.GetValue() )  
Sign up to request clarification or add additional context in comments.

Comments

2

The problem is indeed on the the line you posted. The problem is that the default value for the temp_str is evaluated when the Bind method is called, and not when the event is fired. The palletNumberText field is empty when the event is being bound, because you've only just created the palletNumberText control.

This line has the same effect as the following two:

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 ))

One way around the problem is to move the call to palletNumberText.GetValue() into the body of the lambda, and use a default value such as None for the temp_str parameter:

palletNumberText.Bind(wx.EVT_TEXT, lambda event, temp_str=None: self.onPalletNumberText( event, palletNumberText.GetValue() if temp_str is None else temp_str ))

However, this line is getting quite long and you may be better creating a function instead of trying to cram too much code into a lambda. Another alternative might be to make palletNumberText an attribute of your ClassName class and then have your self.onPalletNumberText method check its contents.

Comments

1

The problem is that you are calling the GetValue method inside your lambda. That executes immediately which means it will grab the value from the text control before it's even shown. In other words, it will always be empty. It is not called every time the event fires.

Instead, you should just call GetValue() inside the event handler itself:

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()

2 Comments

This makes sense, but so does the lambda. Are lambda's a sticky point for programmers? Why 'should' I just put the GetValue() in the event handler. Just curious. Thank you all for the help.
For this problem, I think it just makes more sense. Sometimes you do want to pass something to the event handler using a lambda. It's just not the normal wxPython syntax. Using lambdas like this is more of a Tkinter type thing. It's not bad per se, you just won't see a lot of it done by most wxPython programmers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.