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.
My program draws the fractal using pointSize_max and pointSize variables, which are entered by the user in Tkinter. The problem is that the fractal is drawn before pressing a button (as soon as the program is run), and the program does not draw the fractal when the button is pressed.
pointLabel = tk.Label(frame,text="minimaalne pikkus")
pointLabel.pack()
pointSize = tk.StringVar()
pointEntry = tk.Entry(frame,textvariable=pointSize)
pointEntry.pack()
pointSize.set(str(10))
pointLabel_max = tk.Label(frame,text="maksimaalne pikkus")
pointLabel_max.pack()
pointSize_max = tk.StringVar()
pointEntry_max = tk.Entry(frame,textvariable=pointSize_max)
pointEntry_max.pack()
pointSize_max.set(str(30))
drawButton = tk.Button(frame, text = "Draw a fractal", command=koch(int(pointSize_max.get()), int(pointSize.get())))
# koch function draws the fractal
drawButton.pack()
tk.mainloop()
The koch function is called when the button is created, as part of the parameter evaluation before the tk.Button call. You can create a function object to call instead.
def koch_invoke():
koch(int(pointSize_max.get()), int(pointSize.get()))
drawButton = tk.Button(frame, text = "Draw a fractal", command=koch_invoke)
When your script is compiled it comes to this line and runs the function since you are calling it:
command=koch(int(pointSize_max.get()), int(pointSize.get()))
Try using a lambda to prevent this from happening:
command= lambda x = int(pointSize_max.get()), y = int(pointSize.get()): koch(x, y))
Related
I'm trying to design a function that will display the coordinates of the canvas so i wrote this function inside another function which is the canvas for the solar system simulation. Here is my code:
def solar_system():
top2 = Toplevel()
top2.title("Solar system simulation") #window title
canvas = tk.Canvas(top2, width=1500, height=900, bg = "black") #making the canvas
canvas.pack()
def display_xy_coordinates(event): #function for displaying x and y
widgetxy["text"]=f"x,{event.x} y,{event.y}"
display_xy_coordinates(event)
widgetxy = Label(canvas, font = "Calibri 10", fg = "white", bg = "black") #colour and font for label showing xy coordinates
canvas.bind("<Button-1>", display_xy_coordinates) #Buton-1 = left click on the mouse. This calls the display xy coordinates function
widgetxy.pack() #this label needs to be packed in order to show
canvas.create_window(1267, 34, window=widgetxy) #this is where the label will be placed (top right of canvas)
I have tried every possible way of writing this function inside the main function but i always get this error:
display_xy_coordinates(event)
^^^^^
NameError: name 'event' is not defined
The error is with this line: display_xy_coordinates(event). Like the error says, you haven't defined event so you can't pass this non-existing variable to the function.
The simple solution is to remove that line of code. That function appears to be designed to work only when being called from a binding which automatically passes the event parameter, so it makes no sense to call it outside of that context. After all, it makes no sense to print the x,y coordinate of a click if the user hasn't clicked anywhere.
This question already has answers here:
tkinter creating buttons in for loop passing command arguments
(3 answers)
Closed 2 years ago.
My question relates to tkinter. I am creating a GUI in which there are 31 different buttons with a different logo on each button. Here is how I create those buttons in the main window:
logos = ['ducks.png', 'bruins.png', 'sabres.png', 'flames.png', 'canes.png', 'hawks.png', 'avs.png',
'jackets.png', 'stars.png', 'redwings.png', 'oilers.png', 'panthers.png', 'kings.png',
'wild.png', 'habs.png', 'preds.png', 'devils.png', 'isles.png', 'rangers.png', 'sens.png',
'flyers.png', 'yotes.png', 'pens.png', 'blues.png', 'sharks.png', 'bolts.png', 'leafs.png',
'canucks.png', 'knights.png', 'caps.png', 'jets.png']
for logo in logos:
load = Image.open(logo)
render = ImageTk.PhotoImage(load)
teamButton = Button(self, image=render)
teamButton.image = render
teamButton.place(x=x_axis, y=y_axis)
x_axis += 80
if x_axis >= 300:
y_axis += 55
x_axis = 0
What I am trying to do:
When user clicks certain button for example "ducks" the program prints a value, let's say 3.
Then, when user clicks another button for example "Bruins" the program prints value 2.
My questions are:
How do I bind the button Ducks with value 3 and the button Bruins with value
And is this the best way (for loop) to create these type of buttons? If it's not, what is?
Use functools.partial to make functions on the fly.
from functools import partial
for value, logo in enumerate(logos):
# not sure where this value is coming from ... so used enumerate for now
load = Image.open(logo)
render = ImageTk.PhotoImage(load)
teamButton = Button(self, image=render)
teamButton.image = render
teamButton.config(command=partial(print, value))
teamButton.place(x=x_axis, y=y_axis)
This question already has answers here:
tkinter creating buttons in for loop passing command arguments
(3 answers)
Closed 6 months ago.
from tkinter import *
root = Tk()
def oku():
l1=Label(root,text=0)
myfilerr=open("kayit.txt","r")
content=myfilerr.readlines()
myfilerr.close()
return content
def kisiSec(kisi):
okudeg=oku()
print(kisi)
def main():
i=0
okudeg=oku()
menubar = Menu(root)
menu2=Menu(menubar,tearoff=0)
for i in okudeg:
menu2.add_command(label=i, command=lambda: kisiSec(i))
root.config(menu=menubar)
menubar.add_cascade(label="Kişiler", menu=menu2)
main()
root.mainloop()
Dont judge me im new but there are 3 diffrent names in the text but in main, c1 buttons gives out same name to kisisec()
How can i fix that?
--ITS TURKISH--
use this:
lambda i=i:
in for loop, because something about the reference to the incorrect thing, so you need to save it in the lambda, for the function to access the parameter.
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'm playing around with TKinter trying to make a number generator.
I can't figure out why a new number doesn't get generated when I use this code:
roll = Button(window, text = 'Roll!', command = num())
But it works if I remove the brackets:
roll = Button(window, text = 'Roll!', command = num)
Thanks guys!
Rest of the code:
from tkinter import *
import random
def num():
number = random.randint(1, 6)
num1.configure(text = number)
return
window = Tk()
window.geometry('300x200')
window.title('Dice')
num1 = Label(window, text = 0)
num1.grid(column = 0, row = 0)
roll = Button(window, text = 'Roll!', command = num)
roll.grid(column = 0, row = 1)
window.mainloop()
When you write num() with the parentheses, you're calling the function immediately, and passing its return value as the argument to Button. When you just name the function, you're passing the function object itself as the argument to Button, and it will call the function later (when the button is clicked).
This question already has answers here:
tkinter creating buttons in for loop passing command arguments
(3 answers)
Closed 6 months ago.
I run into small problem trying to create 0-9 number buttons. I want to define 10 buttons for numbers from 0 to 9 in single loop. Each of them is supposed to add its value to self.user_input = tk.StringVar() which will be printed in label. Clicking 5 button, 7 button and then 0 button will give output 570. I try to use lambda to create command for each button, but instead of getting different values I have 9 everywhere. Here is my code:
import tkinter as tk
import tkinter.ttk as ttk
class Gui(tk.Tk):
def __init__(self):
super().__init__()
self.user_input = tk.StringVar()
tk.Label(self, textvariable=self.user_input).grid()
self.create_buttons()
def create_buttons(self):
for x in range(10):
ttk.Button(self, text=x, command=lambda: self.user_input.set(self.user_input.get() + str(x))).grid()
app = Gui()
app.mainloop()
How can I fix code above to make it work as expected (description up)?
Put the bulk of your code in a proper function. A best practice is that a lambda for a widget callback should only ever call a single function. Complex lambdas are difficult to read and difficult to debug.
The second part of the solution is to create a closure. The trick for that is to make the variable you're passing in bound to the lambda as a default argument.
The callback looks something like this:
def callback(self, number):
new_value = self.user_input.get() + str(number)
self.user_input.set(new_value)
Defining each button looks something like this:
def create_buttons(self):
for x in range(10):
button = ttk.Button(self, text=x, command=lambda number=x: self.callback(number))
button.grid()
Pay particular attention to number=x as part of the lambda definition. This is where the current value of x is bound to the number parameter inside the lambda.