Why are functions running before they are called? [duplicate] - python

This question already has answers here:
How can I provide a "callback" to an API?
(5 answers)
Closed last month.
I am making a python script:
import tkinter
def print_the_nothing_thing():
print("I told you, nothing means nothing. For further assistance, please see:")
print("https://www.youtube.com/watch?v=3WNlWyFgLCg")
print("Type the url into the browser.")
#setup the window
window = tkinter.Tk()
menu = tkinter.Menu(window)
window.configure(menu=menu)
view = tkinter.Menu(menu)
file = tkinter.Menu(menu)
menu.add_cascade(label="File", menu=file)
menu.add_cascade(label="View", menu=view)
#here is my problem
view.add_command(label="Nothing here!", command=print_the_nothing_thing())
file.add_command(label="Nothing here!", command=print_the_nothing_thing())
helpm.add_command(label="Help", command=helpy())
window.mainloop()
My problem is that when I define the function, it runs the function first. After closing it, the menu command does nothing.

You need to remove () from those add_command lines, like
view.add_command(label="Nothing here!", command=print_the_nothing_thing)
file.add_command(label="Nothing here!", command=print_the_nothing_thing)
You are calling those functions there, and they return None. If you use just the name of the function, you get a function object.

You're calling the function in add_command:
view.add_command(label="Nothing here!", command=print_the_nothing_thing())
file.add_command(label="Nothing here!", command=print_the_nothing_thing())
helpm.add_command(label="Help", command=helpy())
Instead, point add_command to the function name; don't execute it.
Thus:
view.add_command(label="Nothing here!", command=print_the_nothing_thing)
file.add_command(label="Nothing here!", command=print_the_nothing_thing)
helpm.add_command(label="Help", command=helpy)

Related

Window (Tkinter) in another file shows up whenever the main script is executed [duplicate]

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 9 months ago.
Good day everyone. I've been baffled dealing with my python code. Im using Tkinter for my GUI for our individual school project.
I have this code as a window (for my Create menu in menu bar in main.py) on another file (let's say functions.py):
def createNew(coord):
#create a new window element
createWindow = tk.Tk()
createWindow.title("Create a new tracker")
createWindow.geometry("350x400")
createWindow.focus_force()
createWindow.grab_set()
x = coord[0]
y = coord[1]
createWindow.geometry("+%d+%d" % (x + 250, y + 200))
The above code has that coord argument which receives the input from main.py with this code (the functions.py is imported as funct):
parentPosition = [window.winfo_x(), window.winfo_y()]
...
menubar = tk.Menu(window)
#file menu
file = tk.Menu(menubar, tearoff=0)
file.add_command(label='Create new tracker', command=funct.createNew(parentPosition))
My problem is that whenever I execute the main.py, this window from functions.py automatically shows up even though I didn't select the Create menu from main.py. The intended location is correct anyway.
Actual snapshot of the UI
What is the issue within my code? Any insights would be appreciated.
PS. I intentionally put the function createNew in functions.py rathen than on main.py
You execute the function immediately when you run the line
file.add_command(label='Create new tracker', command=funct.createNew(parentPosition))
This is because, by putting a pair of brackets after the function name, you call it right away, and pass its return value to the add_command function.
In order to get around this, you can use the lambda keyword to delay execution of the function until it is called again:
file.add_command(label='Create new tracker', command=lambda: funct.createNew(parentPosition))
You can find out more about lambda functions here.

Tkinter stringvar dropdown menu [duplicate]

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 9 months ago.
I have three dropdown menus and 3 string variables that will take on the value of the menus, However in the function that I define query, it seems as if the string variables do not take on the value each time I select a new one on the dropdown menu. It will print the set value and do nothing else. Also what's weird is that it was working perfectly and then suddenly didn't work at all.
Really need help on this one thanks.
root=Tk()
root.title('Query')
root.geometry('600x400')
def query():
print(clicked_id_mouse.get())
print(clicked_id_filename.get())
print(clicked_id_researcher.get())
clicked_id_mouse=StringVar()
clicked_id_mouse.set("Choose Mouse Id")
drop_mouse= OptionMenu(root,clicked_id_mouse,*mouse_id)
drop_mouse.place(x=50,y=150)
clicked_id_researcher=StringVar()
clicked_id_researcher.set("Choose Researcher")
researcher= OptionMenu(root,clicked_id_researcher,*r_i)
researcher.place(x=200,y=150)
clicked_id_filename=StringVar()
clicked_id_filename.set("Choose Filename")
filename= OptionMenu(root,clicked_id_filename,*filename)
filename.place(x=350,y=150)
button= Button(root,text="Query",command=query())
button.place(x=210,y=200)
root.mainloop()
When you are assigning a command to a button use "lambda: ...". Otherwise it will execute it only once the button is created. Your code should work as intended by changing
button= Button(root,text="Query",command=query())
into
button= Button(root,text="Query",command=lambda: query())
I hope that helps.

Calling a list in another function - Python [duplicate]

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.

python delay function call [duplicate]

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 7 years ago.
I want to delay a function call. (Or in my mind: python is executing the function in the wrong order). In the below example i could write instead of bf(arg) the two functions bf1 and bf2 and it does work as expected: The function is called whenever the button is pressed. But if i include the arguments in the function the function call is executed only once. Returning the function itself doesn't change the behaviour.
Can you please take a look at it and give me a hint where my logic or understanding of python is wrong.
from tkinter import *
def bf(str):
print(str)
# return print(str) #alternative(same behaviour)
main=Tk(screenName='screen',baseName='base')
button1=Button(master=main,text='b1',command=bf("b1"))
button2=Button(master=main,text='b2',command=bf("b2")) # runs once (and runs here)
button1.pack()
button2.pack()
mainloop()
print('end')
--google and stackoverflow search only return things like delay function call for 1 a specific time interval This is not what i am searching for. :-(
The issue is that you are calling the function when you create the buttons, instead of passing a callable that TK will call when the button is clicked. Normally you would just pass the function itself:
button1=Button(master=main, text='b1', command=bf)
but since you want to pass arguments to bf you will need to wrap it in a lambda:
button1=Button(master=main, text='b1', command=lambda: bf('b1'))
What you do in that line is that you don't pass the function but execute it:
button1=Button(master=main,text='b1',command=bf("b1"))
You could either include only the function name, but then you can't pass a parameter to the function:
button1=Button(master=main,text='b1',command=bf)
or you could make use of lambda:
button1=Button(master=main,text='b1',command=lambda:bf("B1"))

Python 3.4.2 tkinter Menu Auto Calling Function [duplicate]

This question already has answers here:
All tkinter functions run when program starts
(2 answers)
Closed 7 years ago.
I'm very new to python's tkinter gui and I am trying to use it to build a basic test.
I created the menu where one of the menu items must call a function although when I run the program I can see the output from the function before the menu item has been clicked and when the menu item is clicked it does not call the function.
My code is as follows
from tkinter import *
class cl_main():
def __init__(self, master):
lo_mainmenu = Menu(master)
lo_mainmenu.option_add('*tearOff', FALSE)
master.config(menu=lo_mainmenu)
lo_menugroup = Menu(lo_mainmenu)
lo_mainmenu.add_cascade(label="MenuGroup")
lo_menugroup.add_command(label="Command", command=f_message())
def f_message():
print ("This Function Has Been Called")
root = Tk()
co_main = cl_main(root)
root.mainloop()
I can't see what is wrong with it but I'm sure there is something horribly wrong here
lo_menugroup.add_command(label="Command", command=f_message())
callbacks shouldn't have parentheses. As it is, f_message is called right away and its return value is assigned to command, rather than the function object itself.
lo_menugroup.add_command(label="Command", command=f_message)

Categories

Resources