简体   繁体   中英

Will creating a tkinter button in a function, while using lambda as a command, function properly?

I have been creating an application using Tkinter to instantiate the GUI. I am trying to make it object oriented so the code could be used elsewhere making Tkinter easier to use. The problem I've come across is being able to call complex functions with arguments for button commands.

I've tried to learn as much as I can about buttons. I've read and watched videos on binding the command to specific mouse clicks and passing the function using partial to break down the function. These options would not fit the current architecture of the code. The last idea I tried was using lambda to create a temporary function.

def add_button(self, title, command, where, frame):
    button = ttk.Button(frame, text=title,command=lambda: command)
    button.pack(side=where, fill='both', expand=True)
    return button

This is a class that instantiates a page with the desired widgets.

class StartPage(Page):

    def __init__(self, container, controller):
        super().__init__(container, controller)

        title_frame = tk.LabelFrame(self, text='StartPage')
        title_frame.pack(side='top')
        title = tk.Label(title_frame, text='EPA Engine Report Filing', font=('Helvetica', 16))
        title.pack(side='bottom', pady=25)

        buttons = {'Quit': quit(), 'Stuff': do_something()}

        button_frame = tk.Frame(self)
        button_frame.pack(side='top', pady=75)

        for button, command in buttons.items():
            self.add_button(button, command, 'bottom', button_frame)

My specific question is this, when the for loop iterates through the dictionary declared as buttons in StartPage.__init__ , do the lambda functions for the 'Stuff' button overwrite the lambda function for the previous 'quit' button? If this is the case the last button created would be the only button to work, if I understand lambda. When this code is run, nothing appears. When the functions for the buttons don't have parentheses the initial window appears but the buttons do nothing.

Thanks for reading and any advice you can give is appreciated.

There are a couple of problems in your code.

First, your use of lambda is incorrect. When you do lambda: command , the lambda is doing nothing. If you want the lambda to call the command you need to use parenthesis to tell python to execute the function (eg: lambda: command() ). However, if you're not passing any argument then the lambda itself serves no purpose. You can simply tie the command directly to the button (eg: command=command ).

The other problem is that you are incorrectly defining buttons . Consider this code:

buttons = {'Quit': quit(), 'Stuff': do_something()}

The above code is functionally identical to this:

result1 = quit()
result2 = do_something()
buttons = {'Quit': result1, 'Stuff': result2}

In all cases, you need to pass a reference to a function. For example, this should work:

buttons = {'Quit': quit, 'Stuff': do_something}
...
def add_button(self, title, command, where, frame):
    button = ttk.Button(frame, text=title,command=command)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM