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)
Related
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.
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 10 months ago.
from tkinter.ttk import *
import time
root= Tk()
root.title("THis is our other lessons")
root.geometry("600x400")
prog=Progressbar(orient=HORIZONTAL,length=100,mode='determinate')
def bar():
for i in range(1,100,1):
prog['value']=i
root.update_idletasks()
root.after(2000,root.destroy)
prog.pack()
butt=Button(text="Start",command= bar())
butt.pack()
root.mainloop()
I tried this method to run the progress bar but it did not worked with time.sleep, so I tried after method but the output directly reaches to end.
butt=Button(text="Start",command= bar())
The problem is that you call bar() and take the return value as the button's command. This causes bar to execute immediately instead of when the user clicks the button. To fix this, remove the parentheses to make bar itself the command:
butt=Button(text="Start",command= bar)
This question already has answers here:
tkinter creating buttons in for loop passing command arguments
(3 answers)
Closed 2 years ago.
I am configuring a tkinter Menu option on the fly, with a passed in list of menu items and callback functions.
However, whichever menu item is actually selected the same callback is called. I think it is to do with the cmd_func var used to build the lambda changing as the loop that builds the menu options iterates. The value in the lambda ends up changing as the loop iterates so all the lambda's end up pointing ot the last value cmd_func takes? However I can't see how to solve the problem? - I did try enumerating menu_cmds when building the menu, and using the index var to index directly into the array menu_cmds to get at the function value rather than having the intermediate cmd_func var, but that didnt help.
This code replicates the issue;
from tkinter import *
class a:
def __init__(self):
self.root=Tk()
self.m=[ ('name_a',self.command_a),
('name_b',self.command_b) ]
self.control_frame=Frame(self.root)
self.control_frame.pack(side=TOP,fill=X)
self.control=control(self.control_frame,self.m)
self.control.pack()
def command_a(self,data):
print("command_a %s,%s" % data)
def command_b(self,data):
print("command_b %s,%s" % data)
class control(Frame):
def __init__(self,parent,menu_cmds):
Frame.__init__(self,parent)
self.menu_cmds=menu_cmds
self.canvas=Canvas(self,width=800,height=400)
self.canvas.pack(side=LEFT,anchor=W)
self.canvas.create_rectangle(100,100,300,300,fill="#FF0000")
self.canvas.bind("<Button-3>", self.canvas_context_popup)
self.build_canvas_context_menu()
def build_canvas_context_menu(self):
self.canvas_context_menu=Menu(self.canvas, tearoff=0)
for menu_text,cmd_func in self.menu_cmds:
print("menu %s" % menu_text)
cmd=lambda : self.canvas_context_menu_select(cmd_func)
self.canvas_context_menu.add_command(label=menu_text,
command=cmd)
def canvas_context_popup(self, event):
try:
self.popup_at_x=event.x_root-self.canvas.winfo_rootx()
self.popup_at_y=event.y_root-self.canvas.winfo_rooty()
self.canvas_context_menu.tk_popup(event.x_root, event.y_root, 0)
finally:
self.canvas_context_menu.grab_release()
def canvas_context_menu_select(self,cmd_func):
x=self.popup_at_x
y=self.popup_at_y
cmd_func((x,y))
GUI = a()
GUI.root.geometry('1000x600')
GUI.root.update()
GUI.root.mainloop()
Any help much appreciated!
manveti and furas above had it right away, thankyou!
The solution is to change the lambda to be
cmd=lambda x=cmd_func : self.canvas_context_menu_select(x)
For a better explanation than I can give; refer to the comment and info linked by manveti above.
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:
Creating functions (or lambdas) in a loop (or comprehension)
(6 answers)
Closed 6 months ago.
I have a GUI program,
It auto create buttons from a name list,
and connect to a function prints its name.
but when I run this program, I press all the buttons,
they all return the last button's name.
I wonder why this thing happens. can any one help?
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import logging
logging.basicConfig(level=logging.DEBUG,)
class MainWindow(QWidget):
def init(self):
names = ('a','b','c')
lo = QHBoxLayout(self)
for name in names:
button = QPushButton(name,self)
lo.addWidget(button)
self.connect(button,SIGNAL("clicked()"),
lambda :logging.debug(name))
if __name__=="__main__":
app = QApplication(sys.argv)
m = MainWindow();m.init();m.show()
app.exec_()
result like:
python t.py
DEBUG:root:c
DEBUG:root:c
DEBUG:root:c
I see at least one bug in your code.
Replace:
lambda :logging.debug(name)
By:
lambda name=name: logging.debug(name)
See Why results of map() and list comprehension are different? for details.