How to pass arguments to a Button command in Tkinter?

前端 未结 18 2799
夕颜
夕颜 2020-11-21 07:42

Suppose I have the following Button made with Tkinter in Python:

import Tkinter as Tk
win = Tk.Toplevel()
frame = Tk.Frame(master=win).grid(row=         


        
相关标签:
18条回答
  • 2020-11-21 07:51

    The reason it invokes the method immediately and pressing the button does nothing is that action(somenumber) is evaluated and its return value is attributed as the command for the button. So if action prints something to tell you it has run and returns None, you just run action to evaluate its return value and given None as the command for the button.

    To have buttons to call functions with different arguments you can use global variables, although I can't recommend it:

    import Tkinter as Tk
    
    frame = Tk.Frame(width=5, height=2, bd=1, relief=Tk.SUNKEN)
    frame.grid(row=2,column=2)
    frame.pack(fill=Tk.X, padx=5, pady=5)
    def action():
        global output
        global variable
        output.insert(Tk.END,variable.get())
    button = Tk.Button(master=frame, text='press', command=action)
    button.pack()
    variable = Tk.Entry(master=frame)
    variable.pack()
    output = Tk.Text(master=frame)
    output.pack()
    
    if __name__ == '__main__':
        Tk.mainloop()
    

    What I would do is make a class whose objects would contain every variable required and methods to change those as needed:

    import Tkinter as Tk
    class Window:
        def __init__(self):
            self.frame = Tk.Frame(width=5, height=2, bd=1, relief=Tk.SUNKEN)
            self.frame.grid(row=2,column=2)
            self.frame.pack(fill=Tk.X, padx=5, pady=5)
    
            self.button = Tk.Button(master=self.frame, text='press', command=self.action)
            self.button.pack()
    
            self.variable = Tk.Entry(master=self.frame)
            self.variable.pack()
    
            self.output = Tk.Text(master=self.frame)
            self.output.pack()
    
        def action(self):
            self.output.insert(Tk.END,self.variable.get())
    
    if __name__ == '__main__':
        window = Window()
        Tk.mainloop()
    
    0 讨论(0)
  • 2020-11-21 07:51

    For posterity: you can also use classes to achieve something similar. For instance:

    class Function_Wrapper():
        def __init__(self, x, y, z):
            self.x, self.y, self.z = x, y, z
        def func(self):
            return self.x + self.y + self.z # execute function
    

    Button can then be simply created by:

    instance1 = Function_Wrapper(x, y, z)
    button1  = Button(master, text = "press", command = instance1.func)
    

    This approach also allows you to change the function arguments by i.e. setting instance1.x = 3.

    0 讨论(0)
  • 2020-11-21 07:55

    This can also be done by using partial from the standard library functools, like this:

    from functools import partial
    #(...)
    action_with_arg = partial(action, arg)
    button = Tk.Button(master=frame, text='press', command=action_with_arg)
    
    0 讨论(0)
  • 2020-11-21 07:57

    You need to use lambda:

    button = Tk.Button(master=frame, text='press', command=lambda: action(someNumber))
    
    0 讨论(0)
  • 2020-11-21 08:01

    Use lambda

    import tkinter as tk
    
    root = tk.Tk()
    def go(text):
        print(text)
    
    b = tk.Button(root, text="Click", command=lambda: go("hello"))
    b.pack()
    root.mainloop()
    

    output:

    hello
    
    0 讨论(0)
  • 2020-11-21 08:02

    JasonPy - a few things...

    if you stick a button in a loop it will be created over and over and over again... which is probably not what you want. (maybe it is)...

    The reason it always gets the last index is lambda events run when you click them - not when the program starts. I'm not sure 100% what you are doing but maybe try storing the value when it's made then call it later with the lambda button.

    eg: (don't use this code, just an example)

    for entry in stuff_that_is_happening:
        value_store[entry] = stuff_that_is_happening
    

    then you can say....

    button... command: lambda: value_store[1]
    

    hope this helps!

    0 讨论(0)
提交回复
热议问题