0

In the following code, the two ways of constructing buttons act differently:

from Tkinter import *
def buildButton1():
    root = Tk()
    Button( root, command = lambda : foo(1) ).pack()
    Button( root, command = lambda : foo(2) ).pack()

def buildButton2():
    root = Tk()
    buttons = ( Button( root, command = lambda : foo(i) ) for i in range(2) )
    map( lambda button : button.pack(), buttons )

def foo( number ):
    print number

Both methods make Tkinter window with two ostensibly identical button layouts, but in the second example - which seems much more concise were we to add 50 buttons instead of 2 - the value that gets passed into foo is the last iterated i.

So in this case, pushing any button made with buildButton2 prints 1, where buildButton1's buttons print 0 and 1 respectively. Why is there a difference? Is there a way to make buildButton2 work as expected?

Edit It's been pointed out that this is a duplicate question, and that a more correct way of constructing this is to write:

 buttons = ( Button( root, command = lambda i=i : foo(i) ) for i in range(2) )

which gives the desired result. Thanks guys!

en_Knight
  • 5,301
  • 2
  • 26
  • 46
  • Unless I am mistaken, you need `buttons = (Button(root, command=lambda i: foo(i)) for i in range(2))`, this way the value of `i` is passed in to lambda. – Burhan Khalid Oct 31 '13 at 05:33
  • Don't think that's right, Burhan; in fact, it seems to throw an exception, since the button doesn't pass anything pass any arguments into the function – en_Knight Oct 31 '13 at 05:36

1 Answers1

0

Your application should only have 1 TK root. Is this just an example or real code from your application? If it's real code you try to get a TK root every time you 'generate' a button. You should move the root=TK() into your main code as there is just one root for your application. Every window, button.. is a child of this root.

You could try something like this:

from tkinter import *
from tkinter import ttk

    class testWnd( ttk.Frame ):  

        def createWndMain( self ):
            self.BtnLoad = ttk.Button( self, text="Load file", command=self.LoadMyFile )
            self.BtnLoad.grid( column=10, row=10, padx=8, pady=4, sticky=( S, E, W ) )

            self.BtnQuit = ttk.Button( self, text="Quit", command=self.quit )
            self.BtnQuit.grid( column=10, row=20, padx=8, pady=4, sticky=( S, E, W ) )

            self.Spacer = ttk.Frame( self, height = 12 )
            self.Spacer.grid( column = 10, row = 15, sticky = ( S, E, W ) )

            self.columnconfigure( 5, weight = 1 )
            self.rowconfigure( 5, weight = 1 )

        def LoadMyFile( self ):
            pass

        def __init__( self, tkRoot ):
            ttk.Frame.__init__( self, tkRoot )
            tkRoot.title( "My Application v 1.0" )
            tkRoot.columnconfigure( 0, weight = 1 )
            tkRoot.rowconfigure( 0, weight = 1 )
            self.tkRoot = tkRoot
            self.grid( column = 0, row = 0, sticky = ( N, S, E, W ) )
            self.createWndMain()

    tkRoot = Tk()
    myWndMain = testWnd( tkRoot )
    myWndMain.mainloop()
MacDefender
  • 346
  • 2
  • 6
  • It's just example code, I'm good with making the root window :) I'm more concerned with the behavior of the argument the button is passing – en_Knight Oct 31 '13 at 06:10