*Using Eclipse IDE* My button isn't clickable. Python Tkinter - python

I've been trying for about a week now but I can't seem to figure out what I did wrong. My button will not respond when I click it, and even after adding a command it would just display it when I run the program. If I put the disable command, I can see the button change to disabled. Please help if you can.
from tkinter import *
screen = Tk()
screen.title = ("My first")
screen.geometry("800x500")
#create a label
myLabel1 = Label(screen, text = "First Program")
myLabel2 = Label(screen, text = "Yeah Buddy")
#place onto screen using grid system
myLabel1.grid(row=0,column=0)
myLabel2.grid(row=1,column=1)
#Create a text box:
txtfield = Entry(screen, width=50, bg="blue", fg= "white")
txtfield.grid(row=2, column =2 )
#command for click (you need to have function appear before where you intend to use it for it to execute.)
def myClick():
myResponse = Label(screen, text= "Button clicked" + txtfield.get())
myResponse.grid(row=4, column=2)
#make a button
myButton = Button(screen, text="Test Button", command = myClick())
myButton.grid(row=3, column=2)
screen.mainloop()

You're calling myClick instead of passing the function itself as a parameter. command=myClick

Related

how to bind button in tkinter

import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.title("Tic Tac Toe")
root.geometry("505x500")
root.resizable(0,0)
Blank = tk.PhotoImage(file='Blank.png')
X = tk.PhotoImage(file='X.png')
O = tk.PhotoImage(file='O.png')
def configB(event):
print('hello')
btn1 = tk.Button(root,image=Blank)
btn1.place(x=0,y=0)
btn2 = ttk.Button(image=Blank)
btn2.place(x=165,y=0)
btn3 = ttk.Button(image=Blank)
btn3.place(x=330,y=0)
btn4 = ttk.Button(image=Blank)
btn4.place(x=0,y=165)
btn5 = ttk.Button(image=Blank)
btn5.place(x=165,y=165)
btn6 = ttk.Button(image=Blank)
btn6.place(x=330,y=165)
btn7 = ttk.Button(image=Blank)
btn7.place(x=0,y=330)
btn8 = ttk.Button(image=Blank)
btn8.place(x=165,y=330)
btn9 = ttk.Button(image=Blank)
btn9.place(x=330,y=330)
btn1.bind('<Return>',configB)
root.mainloop()
i want to bind btn1 and i want it to work when i press enter but nothing happens when i press enter as per my code it should print hello .
please help thanks in advance.
As #jasonharper said it will work only if button is focused
btn1.focus()
btn1.bind('<Return>', configB)
and if you click other button then it will not work again
so better bind to main winodw
root.bind('<Return>', configB)
Minimal working code
import tkinter as tk
# --- functions --- # PEP8: lower_case_names
def config_b(event):
print('hello')
# --- main ---
root = tk.Tk()
btn1 = tk.Button(root, text='1')
btn1.pack()
btn1 = tk.Button(root, text='2')
btn1.pack()
#btn1.focus()
#btn1.bind('<Return>', config_b)
root.bind('<Return>', config_b)
root.mainloop()
There is no quick answer to this question.
Buttons must be bound so as to duplicate (as close as possible) normal button behaviour.
This includes changing button relief and colors, then restoring button.
Finally it has to execute the button command.
The following example does this for two buttons.
'button' responds to Mouse 'Button-3'
'buttonX' responds to Key 'Return'
import tkinter as tk
def working():
print("Working...")
def actionPress(event):
event.widget.config(
relief = "sunken",
background = "red",
foreground = "yellow")
def actionRelease(event):
event.widget.config(
relief = "raised",
background = "SystemButtonFace",
foreground = "SystemButtonText")
# activate buttons' command on release
event.widget.invoke()
window = tk.Tk()
button = tk.Button(window, text = "press", command = working)
button.pack()
buttonX = tk.Button(window, text = "pressX", command = working)
buttonX.pack()
# bind returns unique ID
boundP = button.bind("<ButtonPress-3>", actionPress)
boundR = button.bind("<ButtonRelease-3>", actionRelease)
boundXP = buttonX.bind("<KeyPress-Return>", actionPress)
boundXR = buttonX.bind("<KeyRelease-Return>", actionRelease)
# This is how to unbind (if necessary)
# button.unbind(""<ButtonPress-3>", boundP)
# button.unbind(""<ButtonRelease-3>", boundR)
# buttonX.unbind(""<KeyPress-Return>", boundXP)
# buttonX.unbind(""<KeyRelease-Return>", boundXR)
window.mainloop()
You don't need parameter in configB method. Also don't need bind for button1. I also add command in button1 widget. Comment out in line 36 #btn1.bind('<Return>',configB)
def configB():
print('hello')
btn1 = tk.Button(root, command=configB)
Result:
Btw, I don't have png image.

How To Repeatedly Delete Differently Named Items

Recently I was working on a program where when one clicked a button, it would delete all of the tkinter buttons they made through a .yml file. Here is an example of what I mean:
(All TKinter Root Init Here)
button1 = Button(root, text="hi")
button2 = Button(root, text="hi again")
button3 = Button(root, text="hi again again")
button4 = Button(root, text="OK this is getting tiring")
button5 = Button(root, text="go away")
button6 = Button(root, text="...")
def del_all():
for i in range(999999999):
button(i).place_forget() #I was hoping to make button(i) give the output button1, then button2, and so on.
root.mainloop()
Try nametowidget in tkinter,example like:
import tkinter as tk
r = tk.Tk()
for i in range(5):
tk.Button(r,text=i).pack()
r.nametowidget(".!button").pack_forget()
r.mainloop()
This will remove the first button.If you want to remove the second button, you need to use r.nametowidget(".!button2").pack_forget()
So for you code,you may need to use:
def del_all():
root.nametowidget(".!button").place_forget()
for i in range(2, 999999999):
root.nametowidget(".!button"+str(i)).place_forget()
About the parameter in the nametowidget, there is a clear description.
You could also use winfo_children and use .widgetName to check whether it is a button,like:
import tkinter as tk
r = tk.Tk()
tk.Label(r, text="test").pack()
for i in range(5):
tk.Button(r,text=i).pack()
for i in r.winfo_children():
if i.widgetName == 'button':
i.pack_forget()
r.mainloop()
The solution would depend on how the buttons are named/stored.
For example, if the buttons were a list. Something like:
buttons = ['button1', 'button2', 'button3', 'button4']
Then you an delete by calling:
buttons.remove()
And that would 'clear' the list.

Tkinter GUI program issue. Entry.get() problem

Working on a project in which I use Tkinter in order to create a GUI that gives a list of software in a drop-down and when a particular software is chosen, it takes you to a separate window where a user's name will be entered and they would be added to a database. With the code I have so far, I am able to link a "submit" button on the second window to a function that prints a confirmation message as a test to make sure the button works. My issue now is trying to get the input from the entry field and link the input to the "Submit" button but I can't seem to find a way to do so. I was wondering if I could get some advice on how to go about this. Would classes need to be used in order to make it work? or can I stick with functions and keep the code relatively simple?
I have added the code for my program below.
import tkinter as tk
from tkinter import *
from tkinter import ttk
root = tk.Tk() # Main window
root.title("Software Licences")
root.geometry("300x300")
frame = ttk.Frame(root, padding="50 0 50 50")
frame.pack(fill=tk.BOTH, expand=True)
tkvar = StringVar()
choices = ['Imagenow', # Dropdown menu with software options
'FileMakerPro',
'Acrobat',
'Office',
'Lotus Notes']
tkvar.set('Acrobat') # Shows default dropdown menu option when program is opened
popupMenu = OptionMenu(frame, tkvar, *sorted(choices))
popupLabel = ttk.Label(frame, text="Choose Software")
popupLabel.pack()
popupMenu.pack()
def software_pages(): # In this function is the 2nd window with for each individual software
top = Toplevel()
top.title("Software Licences")
top.geometry("300x300")
myLabel = Label(top, text=tkvar.get()).pack()
employee_entrylbl = Label(top, text="Employee name").pack()
employee_entry = Entry(top, width=25, textvariable=tk.StringVar) # Entry field for adding user's name
employee_entry.pack() # Entry field is displayed
if tkvar.get() == "Acrobat": # for each if statement, button command is link to the functions
# defined below
button = ttk.Button(top, text="Submit", command=add_to_acrobat).pack()
elif tkvar.get() == "Imagenow":
button = ttk.Button(top, text="Submit", command=add_to_imagenow).pack()
elif tkvar.get() == "FileMakerPro":
button = ttk.Button(top, text="Submit", command=add_to_filemakerpro).pack()
elif tkvar.get() == "Office":
button = ttk.Button(top, text="Submit", command=add_to_office).pack()
else:
button = ttk.Button(top, text="Submit", command=add_to_lotusnotes).pack()
exit_button = ttk.Button(top, text="Exit", command=top.destroy).pack() # Exit button for second window
add_emp_button = ttk.Button(frame, text="Next", command=software_pages) # "Next" button in the main window takes the
# user to the second window
add_emp_button.pack()
# Functions below are linked to the button commands of each software in the second window function defined earlier.
# They print out specified messages that confirm the user had been added
def add_to_acrobat():
return print("User added to Acrobat")
def add_to_lotusnotes():
print("User added to IBM")
def add_to_imagenow():
print("User added to imagenow")
def add_to_office():
print("User added to 365")
def add_to_filemakerpro():
print("User added to FMP")
def click_button(): # Function for Exit button for main window
root.destroy()
exit_button = ttk.Button(frame, text="Exit", command=click_button) # Exit button for main window
exit_button.pack()
root.mainloop()
You can pass parameters to the command of tkinter.command using partial from the functools module.
in your case:
button = ttk.Button(top, text="Submit", command=partial(add_to_acrobat, employee_entry)).pack()
in the above line, I send the employee_entry(Which holds your desired text) to the add_to_acrobat function
and the add_acrobat function should look like this:
def add_to_acrobat(e):
print(e.get())
return print("User added to Acrobat")
Hope it helps

Tkinter Input/Entry in Python

So I am trying to when the person clicks on the button I created, to display the text they wrote on the input field but for some reason when I click the button it displays:
.!entry
And I don't know what I am doing wrong since I am new to python so I wanted to know how to fix this problem, here's my code and thank you since any help is appreciated!
from tkinter import *
screen = Tk()
def print_input():
text2 = Label(screen, text=input_field)
text2.grid(row=1, columnspan=3)
text = Label(screen, text="Write to print:")
text.grid(row=0, column=0)
input_field = Entry(screen)
input_field.grid(row=0, column=1)
submit_button = Button(screen, text="Print!", fg="yellow", bg="purple",
command=print_input)
submit_button.grid(row=0, column=2)
screen.mainloop()
Change:
def print_input():
text2 = Label(screen, text=input_field)
to:
def print_input():
text2 = Label(screen, text=input_field.get())
# ^^^^^^
You're telling the text of the label to be set to the Entry widget instead of the Entry widget's content. To get the content of the Entry widget, use the .get() method.
The funky string you're seeing in the label is the tkinter name for the Entry widget.

How to get widget name in event?

from tkinter import *
main = Tk()
def flipper(event):
# I'd like to do this:
#if widgetname == switcher:
#do stuff
#if widgetname == switcher1:
#do stuff
return
switcher = Label(main, bg='white', text="click here", font="-weight bold")
switcher.grid()
switcher.bind("<Button-1>", flipper)
switcher1 = Label(main, bg='white', text="click here", font="-weight bold")
switcher1.grid()
switcher1.bind("<Button-1>", flipper)
switcher2 = Label(main, bg='white', text="click here", font="-weight bold")
switcher2.grid()
switcher2.bind("<Button-1>", flipper)
switcher3 = Label(main, bg='white', text="click here", font="-weight bold")
switcher3.grid()
switcher3.bind("<Button-1>", flipper)
switcher4 = Label(main, bg='white', text="click here", font="-weight bold")
switcher4.grid()
switcher4.bind("<Button-1>", flipper)
switcher5 = Label(main, bg='white', text="click here", font="-weight bold")
switcher5.grid()
switcher5.bind("<Button-1>", flipper)
main.mainloop()
In my event function I'd like to do different things based on the label that is clicked. What im stumped on is that I can only get the identifier number of the widget that is clicked, not the name. If I could get the identifier of all my widgets then I could do:
def flipper(event):
if event.widget == switcher.identifier():
do stuff
but I can't find how to get the id of a specified widget either...
How can I get the name of a widget by its identifier (event.widget())?
Or how can I get the identifier of a specified widget name?
If neither are possible, then I'd have to make a different function and bind for each label which is a lot of work that hopefully is not necessary.
Edit:
from tkinter import *
main = Tk()
def flipper(event, switch):
if switch.widget == 's1':
print("got it")
switcher = Label(main, bg='white', text="click here", font="-weight bold")
switcher.grid()
switcher.bind("<Button-1>", flipper)
switcher.widget = 's1'
main.mainloop()
You can't get the variable name that the widget is assigned to, that would be relatively useless. A widget could be assigned to more than one variable, or none at all.
Getting the label text
You have access to the actual widget, and you can use that to get the text that is on the label. Your example shows that all labels are the same, so this might not be useful to you:
def flipper(event):
print("label text:", event.widget.cget("text"))
Using a custom widget name
You can also give a widget a name. You can't get back precisely the name, but you can come very close. For example, if you create a label like this:
switcher = Label(main, name="switcher", bg='white', text="click here", font="-weight bold")
You can get the string representation of the widget by splitting on "." and taking the last value:
def flipper(event):
print("widget name:", str(event.widget).split(".")[-1])
Passing a name via the binding
Finally, you can set up your bindings such that the name is sent to the function:
switcher.bind("<Button-1>", lambda event: flipper(event, "switcher"))
switcher1.bind("<Button-1>", lambda event: flipper(event, "switcher1"))
You can use event.widget to get standard parameters from clicked widget
example:
import tkinter as tk
def callback(event):
print(event.widget['text'])
main = tk.Tk()
switcher = tk.Label(main, text="click here")
switcher.grid()
switcher.bind("<Button-1>", callback)
main.mainloop()
You can assign own variables to widgets
switcher.extra = "Hello"
and then get it
event.widget.extra
example:
import tkinter as tk
def callback(event):
print(event.widget['text'])
print(event.widget.extra)
main = tk.Tk()
switcher = tk.Label(main, text="click here")
switcher.grid()
switcher.bind("<Button-1>", callback)
switcher.extra = "Hello"
main.mainloop()
You can use lambda to bind function with arguments
bind("<Button-1>", lambda event:callback(event, "Hello"))
example:
import tkinter as tk
def callback(event, extra):
print(event.widget['text'])
print(extra)
main = tk.Tk()
switcher = tk.Label(main, text="click here")
switcher.grid()
switcher.bind("<Button-1>", lambda event:callback(event, "Hello"))
main.mainloop()
I had the same issue I found easy way was to use bind method.
apparent name property is private but can be accessed via _name
This is useful if you plan to generate widgets dynamically at runtime
# Import Module
from tkinter import *
# create root window
root = Tk()
# root window title and dimension
root.title("Welcome to Test window")
# Set geometry (widthxheight)
root.geometry('350x200')
#adding a label to the root window
lbl = Label(root, text = "Press a button")
lbl.grid()
#define mouse up event
def mous_up(ev:Event):
#get calling widget from event
sender:Button = ev.widget
#set label text
lbl.configure(text = sender._name + " up")
#read foreground color from button
#If red make green, else make red
if sender.cget('fg') == "red":
#normal color
sender.configure(fg='lime')
#mouse over color
sender.configure(activeforeground='green')
else:
#normal color
sender.configure(fg="red")
#mouse over color
sender.configure(activeforeground='darkred')
#define mouse down event
def mous_down(ev:Event):
lbl.configure(text = str(ev.widget._name) + " down")
# button widget with red color text
# inside
btn = Button(root, text = "Click me" ,
fg = "red",name = "button-A")
#bind mouse up and mouse down events
btn.bind('<ButtonRelease-1>',mous_up)
btn.bind('<Button-1>',mous_down)
# set Button grid
btn.grid(column=0, row=1)
#Create another button
btn = Button(root, text = "Click me2" ,
fg = "red",name="button2")
#bind mouse up and mouse down events
btn.bind('<ButtonRelease-1>',mous_up)
btn.bind('<Button-1>',mous_down)
#absolute placement of button instead of
#using grid system
btn.place(x=50,y=100)
# all widgets will be here
# Execute Tkinter
root.mainloop()
Quick and dirty - you could have the function check a switcher attribute.
def flipper(event, switch):
if switch.widget == 's1':
do_stuff
return stuff
if switch.widget == 's2':
do_stuff
return stuff
switcher1.widget = 's1'
switcher2.widget = 's2'
I know this is an old post, but I had the same problem and I thought I should share a solution in case anyone is interested. You can give your widget a name by creating a subclass of the widget. E.g. "Button" is a widget. You can make a child widget "MyButton" which inherits from button and then add an instance variable to it (e.g. name, uniqueID etc.)
Here is a code snippet
class MyButton(Button):
def __init__(self, master = None, textVal = "", wName = ""):
Button.__init__(self, master, text = textVal)
self.widgetID = wName #unique identifier for each button.
When you want to create a new button widget, use
b = MyButton(.....),
instead of
b = Button(.......)
This way, you have all the functionality of a button, plus the unique identifier.

Categories