This question already has answers here:
Why is my Tk button being pressed automatically?
(2 answers)
Closed 8 years ago.
I'm using Python and TkInter to build a GUI where a certain command is called when a button is pressed. The relevant code looks like this:
class Main(Frame):
def __init__(self, parent):
self.generate_noise_button = Button(root, text="Add noise and save", command=self.generate_noise())
...
def generate_noise(self):
header.generate_noise()
If I place a breakpoint in the generate_noise() method and run the program, the breakpoint is instantly hit despite never being called or the button being pressed. Furthermore whenever I actually do press the button the method is never called making the button completely useless. Why?
self.generate_noise_button = Button(root, text="Add noise and save", command=self.generate_noise())
When you provide a command argument, you're not supposed to add parentheses to the end.
self.generate_noise_button = Button(root, text="Add noise and save", command=self.generate_noise)
You want the command to refer to the method object, not the value that the method returns after it is called.
Related
This question already has an answer here:
Tkinter assign button command in a for loop with lambda [duplicate]
(1 answer)
Closed 7 months ago.
I used for loop to render 15 buttons, and each button invokes the same function to do something. My question is how to determine which button is clicked?
My code snippet is like below:
for number in range(1, 16):
ttk.Button(bottom_frame, text='Read', command=read_one).grid(column=4, row=number, padx=5, pady=5)
I want to reuse the function read_one() for every button, but don't know how to determine which button is clicked. Any comment is appreciated!
Here's my test code: https://pastebin.com/fWyyNVw7
Since the command callback doesn't get passed any parameters by default (like the calling control), there's no easy option.
However, you could use something like this:
for number in range(1, 16):
ttk.Button(bottom_frame, text='Read', command=lambda number=number: read_one(number)
).grid(column=4, row=number, padx=5, pady=5)
That way, read_one will be called with the number passed. Note that you'd need your read_one function to deal with it, e.g.:
def read_one(number):
# do something with number, since it tells you what button was pushed
...
This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 3 years ago.
I am trying to get a button to do some stuff in Python (using Tkinter). I want the button to get the current choice of a combobox and print it on screen.
The graphical layout is 3 separate frames, but both the button and the combobox reside in the same frame (frame #2).
The problem is that i cannot refer to the combobox. The errors i am getting read:
Frame object has no attribute 'box'
Window object has no attribute 'box'
self.box=ttk.Combobox(self.frame2 , values[...])
self.button1=tk.Button(self.frame2, command= self.wipe(), text=...)
def wipe(self):
self.box.get()
ALTERNATIVELY i tried:
def wipe(self):
self.frame2.box.get()
The goal is to simply get the selected choice from the Combobox.
HERE IS MINIMAL CODING THAT PRODUCES THE SAME ERROR:
import tkinter as tk
from tkinter import ttk
class window():
def __init__(self,root):
self.frame=tk.Frame(root)
self.key=tk.Button(self.frame,text='PRESS ME',command=self.wipe())
self.box=ttk.Combobox(self.frame, options=['1','2','3'])
self.frame.pack()
self.key.pack()
self.box.pack()
def wipe(self):
self.box.get()
master=tk.Tk()
master.geometry('400x400')
app=window(master)
master.mainloop()
I would add the tag "tkinter" to the question.
Try the following:
def wipe(self):
# code
self.box=ttk.Combobox(self.frame2 , values[...])
self.button1=tk.Button(self.frame2, command=wipe, text=...)
Notice the following:
I first defined wipe, only then used it.
I am not quite sure why you wanted to do command=self.wipe(), as there are two issues here. First, you are setting command to the result of self.wipe() which is NOT a function. Second, you haven't defined self.wipe, you defined wipe.
command=wipe Sets the command keyword argument to the
function wipe
Its been long since I dealt with tkinter, if this doesn't work, I'll try to help by checking the docs again.
This question already has answers here:
How to pass arguments to a Button command in Tkinter?
(18 answers)
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 4 years ago.
Im trying to get this Listbox in tkinter to update from a sqlite3 database when a button is clicked. I actually had it working using root.after(1000, function) method but the cursor kept resetting every time it was updated.
At the moment I can't get the listbox to populate at the button click.
I would love any help. Thanks!
root=Tk()
ListBox1 = Listbox(root)
ListBox1.grid(row=0, column=0 , sticky='nsew')
def ListUpdate():
listlist = []
#populates list from sql database in a for loop
return listlist
def ListPopulate(listlist):
ListBox1.delete(0, END)
for i in range(0,len(listlist[i]):
ListBox1.insert(END, listlist[i])
ButtonUpdate = Button(root, text='Update', command=ListPopulate(listlist))
ButtonUpdate.grid(row=5, column=6, sticky='nsew')
You're using command wrong. Replace:
Button(..., command=ListPopulate(listlist))
with:
Button(..., command=lambda l=ListUpdate(): ListPopulate(l))
Your command= argument for your Button calls ListPopulate(listlist) when the button is created and assigns its result (which is None, since you don't return anything from that function) as the command. You have therefore told the Button object that it has no command.
You're naturally going to run into problems passing the list to all the places it needs to go in an event-driven system. One approach is to make the list ListList a global variable. Define it outside all your functions at the top of the script, with your other variables:
ListBox1 = Listbox(root)
ListBox1.grid(row=0, column=0 , sticky='nsew')
listlist = []
Next, change the first line of ListUpdate() to use a slice assignment to empty out the existing list object, so you don't need to declare the object global in that function.
def ListUpdate():
listlist[:] = []
Then change ListPopulate() to take no arguments, since it's going to use the global listlist.
def ListPopulate():
Finally, write your Button() constructor to pass ListPopulate rather than calling it.
ButtonUpdate = Button(root, text='Update', command=ListPopulate)
Globals are generally bad practice. What you probably should do is subclass Listbox and give it an attribute that holds the list. Then your two functions would be methods of that class. (In fact, you probably want to update the displayed list on screen every time you change its contents... so you should have one method, not two.) I'll leave that as an exercise for when you learn object-oriented programming.
This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 5 years ago.
I am writing code to pass two variables to a function on the click of a button. The issue is that it is doing so before the button is pressed. What am I doing wrong?
calcButton = Button(window, text="Calculate Weight",
command=window.calc(5,10))
calcButton.place(x=225, y=85)
answertextLabel = Label(window, text="Answer:")
answertextLabel.place(x=225, y=65)
answerLabel = Label(window, text=answervar)
answerLabel.place(x=275, y=65)
def calc(window, diameter, density):
math = diameter + density
print (math)
When you do window.calc(5,10) the function gets executed.
You need to wrap it in another function:
command=lambda: window.calc(5,10)
You aren't passing the function as an argument to the Button constructor; you are passing the return value of one particular call to that function. Wrap the call in a zero-argument function to defer the actual call until the button is clicked.
calcButton = Button(window,
text="Calculate Weight",
command=lambda : window.calc(5,10))
This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 6 years ago.
I have the following lines in a large program.
username = Entry(loginPage)
password = Entry(loginPage)
button1 = Button(loginPage,text = "Login", fg = "red", command = loginClicked(username.get(),password.get()))
When the program is run, the function loginClicked runs once at the start (when the fields are empty and the button hasn't been clicked) and that is the only time it runs. After, when the button is clicked the function doesn't run at all. A print statement in the function confirms this.
As mentioned in the comments, when you create the widget you are calling ('running') the function before the widget is created, instead of passing the function handle (may be wrong terminology here) to the widget option command=.
This can be solved by using anonymous functions with lambda:
button1 = Button(root,text = "Login",
fg = "red",
command = lambda: loginClicked(username.get(), password.get()))
This creates a 'throw-away' function to feed into Tkinter's callback, which calls your function loginClicked() with its correct arguments.
You can also read effbot.org for more information on Tkinter callbacks