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=
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()
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
.
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)
You need to use lambda:
button = Tk.Button(master=frame, text='press', command=lambda: action(someNumber))
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
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!