Tkinter Stop Program Execution Button - python

I am attempting to construct a simple game using the Tkinter GUI. The first portion of the game is asking if one wants to play. My Tkinter looks as follows:
window = tk.Tk()
window.rowconfigure(0, minsize=50, weight=1)
window.columnconfigure([0, 1, 2], minsize=50, weight=1)
lbl_value = tk.Label(master=window, text="Welcome!")
lbl_value.grid(row=0, column=1)
lbl_value = tk.Label(master=window, text="Would you like to play?")
lbl_value.grid(row=1, column=1)
btn_yes = tk.Button(master=window, text="Yes", command=window.destroy)
btn_yes.grid(row=2, column=0, sticky="nsew")
btn_no = tk.Button(master=window, text="No", command=**??**)
btn_no.grid(row=2, column=2, sticky="nsew")
window.mainloop()
The "Yes" button is operating as intended, and continuing with the rest of the code. The "No" button however, I am not sure how to get it to exit the the running of the program all together (not just the window), or even better, how to get it to open an additional window stating "Maybe next time", then ending the program when that window is exited out of.

Create a new function where you can define a new tkinter screen which will appear when user press NO button See
def no_button_function(): # function that will be called when user pressed no button
new_window = tk.Toplevel(window)
new_window.title('See You Next Time')
# create the good bye message using labels and buttons accordingly
and now pass this function to NO buttton
btn_no = tk.Button(master=window, text="No", command=no_button_function)
btn_no.grid(row=2, column=2, sticky="nsew")
Hope You Got This.
Tick Mark If Satisfied

Related

Messed Up Spacing After Button Click in Tkinter

I'm trying to create a GUI using Tkinter for a Pip-boy from Fallout 3. I'm running into a problem where after I click a button in one of the frames, the spacing between the buttons gets messed up. This spacing change happens for all but one of the buttons in the frame (the Lockpick one).
This is what I want the button spacing to look like (what it looks like before I click a button):
This is what happens after I click a button (in this case the Barter one)
Here is the code I am using:
from tkinter import *
# to read descriptions of each skill from a text file
with open("skills.txt") as f:
lines = f.readlines()
# function that updates the label with a different description when the corresponding button is clicked
def show_skill_desc(index):
desc['text'] = lines[index-1]
# makes the window and frame
root = Tk()
root.geometry("1024x600")
root.title("Skills")
frame = Frame(root)
frame.grid()
# creates the label
Label(root, text="Stats").grid(row=0, column=0)
# list of skills which will each have their separate labels
skills_list = ["Barter", "Big Guns", "Energy Weapons", "Explosives", "Lockpick", "Medicine",
"Melee Weapons", "Repair", "Science", "Small Guns", "Sneak", "Speech", "Unarmed"]
# placing the label in the frame
desc = Label(root, text="", padx=30, wraplength=600, justify=LEFT)
desc.grid(row=2, column=1)
# creates a button for each skill
button_list = []
for i in range(12):
button_list.append(Button(root, text=skills_list[i], width=40,
height=2, command=lambda c=i: show_skill_desc(button_list[c].grid_info()['row']), padx=0, pady=0))
button_list[i].grid(row=i+1, column=0)
root.mainloop()
The purpose of the GUI is to display the description of each skill, when the button for a skill is clicked.
Does anyone know why the spacing change happens? Thank you!

How to disable the following button in Tkinter?

I have a hard time trying to disable the buttons I don't need in Tkinter, until some condition is met.
The following code it's a reference of what I'm doing:
ID_Personal=[]
ID_Product=[]
from tkinter import *
window = Tk()
def addProduct():
def callback():
ID_Product.append(ID_Product_Entry.get())
print("Product registered")
windowProduct = Tk()
lblProduct = Label(windowProduct, text="ID: ")
lblProduct.grid(padx=10, pady=10, row=0, column=0)
ID_Product_Entry = Entry(windowProduct)
ID_Product_Entry.grid(padx=10, pady=10, row=0, column=1)
btnAdd = Button(windowProduct, text="Submit",command=callback)
btnAdd.grid(padx=10, pady=10, row=1, column=0)
windowProduct.mainloop()
def addPersonal():
def callbackPersonal():
ID_Personal.append(ID_Personal_Entry.get())
print("Employee registered")
windowPersonal = Tk()
lblProduct = Label(windowPersonal, text="ID: ")
lblProduct.grid(padx=10, pady=10, row=0, column=0)
ID_Personal_Entry = Entry(windowPersonal)
ID_Personal_Entry.grid(padx=10, pady=10, row=0, column=1)
btnAddP = Button(windowPersonal, text="Submit",command=callbackPersonal)
btnAddP.grid(padx=10, pady=10, row=1, column=0)
windowPersonal.mainloop()
btnProduct = Button(window,text="Product",command=addProduct)
btnProduct.grid(padx=10, pady=10, row=0, column=0)
btnPersonal = Button(window,text="Personal",command=addPersonal)
btnPersonal.grid(padx=10, pady=10, row=1, column=0)
window.mainloop()
Basically what I need to do is disable the button btnProduct when my ID_Personal list it's empty. Once some personal has been registered, then it must be active again. I've been trying but nothing seems to work. I don't know if I'm using the if condition wrongly or what. Thank you in advance for your help.
You can set the state of btnProduct to "disabled" when you create it, as the list ID_Personal is initially empty.
btnProduct = Button(window,text="Product",command=addProduct,state='disabled')
You can then change the button state to "normal" in the callbackPersonal function using btnProduct.config(state='normal')
This will normalize the button the first time an item is added to ID_Personal
Now if your app demands that the button should go back to "disabled" if ID_Personal is empty and turn "normal" only when ID_Personal is non-empty then the above solution won't work. In that case, we need to recursively update the widgets based on changing conditions. The "after" function can help us to achieve that.
def update():
if len(ID_Personal) > 0:
btnProduct.config(state='normal')
else:
btnProduct.config(state='disable')
window.after(1,update)
update()
Adding the above code to your program will help you update your widgets (button in this case) continuously after every 1 millisecond.
Set the state disabled when you create the button.
btnProduct = Button(window,text="Product",command=addProduct, state="disabled")
And in the callbackPersonal function set the state active.
btnProduct.config(state="active")
This way when you run the program the product button will be disabled, but once you add your first personal, the button will be active.

Python Tkinter simple value process

I just new for the GUI and need little help.
a=int(input())
if a==0:
print("hi")
else:
print("hello")
I want to change input process to click button, like a switch.
left button -> a=0
right button -> a=1
window=tkinter.Tk()
window.title("")
window.geometry("640x640+100+100")
window.resizable(True, True)
a=tkinter.Button(window, text="left")
a.pack()
b=tkinter.Button(window, text="right")
b.pack()
window.mainloop()
I can see left, right button but I don't know how to put values.
Is there any example I can use?
Thanks
Does this example help You:
from tkinter import Tk, Button
def switch(btn1, btn2):
btn1.config(state='disabled')
btn2.config(state='normal')
print(btn1['text'])
window = Tk()
window.title("")
on = Button(window, text="On", command=lambda: switch(on, off))
on.pack(side='left', expand=True, fill='x')
off = Button(window, text="Off", command=lambda: switch(off, on))
off.pack(side='left', expand=True, fill='x')
off.config(state='disabled')
window.mainloop()
If You have questions ask but here is pretty good site to look up tkinter widgets and what they do, their attributes.
Also I suggest You follow PEP 8
You need to add a function to each one that will be executed when the buttons are clicked like this:
import tkinter as tk
def left_clicked():
print("Left button clicked")
right_button.config(state="normal") # Reset the button as normal
left_button.config(state="disabled") # Disable the button
def right_clicked():
print("Right button clicked")
right_button.config(state="disabled")
left_button.config(state="normal")
window = tk.Tk()
window.title("")
window.geometry("640x640+100+100")
# window.resizable(True, True) # Unneeded as it is already the default
left_button = tk.Button(window, text="left", command=left_clicked)
left_button.pack(side="left")
right_button = tk.Button(window, text="right", command=right_clicked,
state="disabled")
right_button.pack(side="right")
window.mainloop()

Tkinter: How to assign two commands to a button via a function?

I am wanting to make an 'Enter Name' entry that prints a welcome message to the user. I recently posted asking for help on how to switch frames in tkinter. I figured it out and solved that problem.
However, now I want to switch frames and print an entry to a label when hitting a button. I don't receive any errors in my code however the returnEntry() function doesn't do anything. It doesn't raise the frame and I don't think it retrieves the entry text either.(without the returnEntry() function the frame does raise the frame, but with the code it doesn't. Does that make sense or am I complicating things?
Here is the code:
def show_frame(frame):
frame.tkraise()
def returnEntry():
result=NameEntry.get()
Label3.config(text=result)
def WelcomeName():
show_frame(f3)
returnEntry()
f1 = Frame(root)
f2 = Frame(root)
f3 = Frame(root)
f4 = Frame(root)
for frame in (f1, f2, f3, f4):
frame.config(width=500,height=500, bg="light blue")
frame.place(relx=0.5,rely=0.5,anchor="center")
#First Page
Button(f1, text='Click to Play', command=lambda: show_frame(f2)).place(relx=0.5,rely=0.5,anchor="center")
Label(f1, text='Magic 8 Ball', fg="White", bg="dark blue",
font="Veranda 19").place(relx=0.5,rely=0.20,anchor="center")
#Second page
Label(f2, text='Enter your name:',fg="White", bg="dark blue",
font="veranda 17").place(relx=0.5,rely=0.40,anchor="center")
NameEntry=Entry(f2,font="veranda 15").place(relx=0.5,rely=0.5,anchor="center")
Button2=Button(f2, text='Continue', font="veranda 15",
command=lambda: returnEntry).place(relx=0.5,rely=0.60,anchor="center")
#Third Page
Label3=Label(f3,text="",bg="light blue",font="veranda 15").place(relx=0.5,rely=0.35,anchor="center")
Label4=Label(f3, text="Ask me a yes or no question and reveal the truth" , bg="light blue",font="veranda 15")
Label4.place(relx=0.5,rely=0.45,anchor="center")
QuestionEntry=Entry(f3, font="veranda 15").place(relx=0.5,rely=0.52,anchor="center")
Button(f3, text='Ask away', command=lambda: show_frame(f4)).place(relx=0.5,rely=0.6,anchor="center")
Sorry for sloppy code etc...
You can't. You will have to make a 3rd function that calls the two you want, and give that 3rd function to the Button command.
def on_click():
do_thing_1()
do_thing_2()
btn = Button(command=on_click)
I highly recommend you stay away from lambda until you know how it works.
Also, you shouldn't initialize and layout widgets on the same line, it leads to bugs. Always use 2 lines.
# BAD: NameEntry is None, and can't be used
NameEntry=Entry(f2,font="veranda 15").place(relx=0.5,rely=0.5,anchor="center")
# good: NameEntry is an Entry instance, and can be used later
NameEntry=Entry(f2,font="veranda 15")
NameEntry.place(relx=0.5,rely=0.5,anchor="center")

I have a Toplevel button in tkinker that I want to close the window and then perform a function

So far I have created a frame with some functioning buttons/menus. One of my menu buttons opens a new Toplevel window. This new Toplevel window is basically a forum fill out page. At the end of the page is a done button. This done button closes the tkiniter Toplevel window while leaving the root window. I wish to execute lines of code after the button is pressed.
My first idea was to set the done button command to make the window 'withdrawn'. If I do this, it does withdraw the window but if I try to run an if check the check will already have been checked before the button is pressed. The most simple solution to this would be to create a function the withdraws the window and does the other stuff I am wanting, however, when I try to pass a function as the command for the Toplevel done button it does not call the function.
Any advice how to make the button close the window and then perform additional code (Only after the button is pressed) would be greatly appreciated. I have attached the section of code in question below. Thank You in advance for your help. (Side note Computer class is handled in another file). (I am using Python 3.x)
def draw_new_computer_entry(self):
t = Toplevel(self)
t.resizable(0,0)
t.wm_title("Solution Center: Add New Computer")
t.geometry("300x300")
nameLabel = Label(t, text="Computer Name:")
nameLabel.place(x=0,y=10)
a = computer()
comp_nameEntry = Entry(t, width=30)
comp_nameEntry.place(master=None, x=100, y=10)
a.name = comp_nameEntry.get()
comp_makerEntry= Entry(t,width=30)
comp_makerEntry.place(x=100, y=50)
a.maker = comp_makerEntry.get()
makerLabel= Label(t, text="Maker:")
makerLabel.place(x=55,y=50)
graphics_cardEntry= Entry(t, width=30)
graphics_cardEntry.place(x=100,y=90)
a.gpu = graphics_cardEntry.get()
graphics_cardLabel= Label(t, text="Graphics Card:")
graphics_cardLabel.place(x=15, y=90)
processorEntry= Entry(t, width=30)
processorEntry.place(x=100, y=130)
a.processor = processorEntry.get()
processorLabel= Label(t, text="Processor:")
processorLabel.place(x=38, y=130)
hard_driveEntry= Entry(t, width=30)
hard_driveEntry.place(x=100, y=170)
a.hard_drive = hard_driveEntry.get()
hard_driveLabel= Label(t, text="Hard Drive:")
hard_driveLabel.place(x=30, y=170)
ramEntry= Entry(t, width=30)
ramEntry.place(x=100, y=210)
ramLabel= Label(t,text="Ram:")
ramLabel.place(x=65,y=210)
doneButton = Button(t, text="done", command=t.withdraw)
doneButton.place(x=265, y=275)
All you have to do is create a function that closes the window and then performs additional code.
Here is a snippet of your code:
def donePressed():
t.withdraw() # Or t.destroy(), depending if you need to open this window again
# Enter Code Here
print('code after window close')
doneButton = Button(t, text="done", command=donePressed)
doneButton.place(x=265, y=275)

Categories