My program has an entry widgets called pizza and sandwich. If the user begins typing in the pizza box the sandwich box should be disabled. If the user begins typing in the sandwich box then the pizza box should be disabled. Box entry boxes should take a float value. The user can pick either box to type the price when they finish typing they should click the submit button and the price should print out. I am trying to figure out how to check for empty floats so the if else statement can change state.
import tkinter as tk
root = tk.Tk()
root.geometry("600x400")
pizza = tk.DoubleVar()
sandwich = tk.DoubleVar()
def click(event):
if pizza.get() != '':
sandwich_entry.config(state=tk.DISABLED)
pizza_entry.config(state=tk.NORMAL)
if sandwich.get() != '':
pizza_entry.config(state=tk.DISABLED)
sandwich_entry.config(state=tk.NORMAL)
if pizza.get() == '' and sandwich.get() == "":
sandwich_entry.config(state=tk.NORMAL)
pizza_entry.config(state=tk.NORMAL)
print("price: " + str(pizza))
print("price: " + str(sandwich))
pizza_label = tk.Label(root, text='pizza')
pizza_entry = tk.Entry(root, textvariable=pizza)
pizza_entry.bind('<KeyRelease>', click)
sandwich_label = tk.Label(root, text='sandwich')
sandwich_entry = tk.Entry(root, textvariable=sandwich)
sandwich_entry.bind('<KeyRelease>', click)
button = tk.Button(root, text='Submit',)
pizza_label.grid(row=0, column=0)
pizza_entry.grid(row=0, column=1)
sandwich_label.grid(row=1, column=0)
sandwich_entry.grid(row=1, column=1)
button.grid(row=2, column=0)
root.mainloop()
Related
I am trying to figure out a way to change a button's text and functionality after I have clicked the Submit button a second time. In the below instance, I am trying to:
1) Change the button's text from Submit to Close after I have entered in the username/password fields for SecondName and have clicked Submit
2) Use the Close() function to close the window.
I have attempted to accomplish these two processes by using an if/else statement.
Tkinter Code
import tkinter as tk
root = tk.Tk()
user_var = tk.StringVar()
pass_var = tk.StringVar()
entries = {}
def Submit():
user = user_var.get()
passw = pass_var.get()
label_text = user_label["text"]
char = label_text.split()[0]
entries[char] = (user, passw)
if char == "FirstName":
user_label["text"] = "SecondName " + user_label["text"].split()[1]
pass_label["text"] = "SecondName " + pass_label["text"].split()[1]
user_var.set("")
pass_var.set("")
print(entries)
def Close():
root.quit()
user_label = tk.Label(root, text="FirstName Username", width=21)
user_entry = tk.Entry(root, textvariable=user_var)
pass_label = tk.Label(root, text="FirstName Password", width=21)
pass_entry = tk.Entry(root, textvariable=pass_var, show="•")
if user_entry["text"] == "SecondName":
sub_btn = tk.Button(root, text="Close", command=Close)
else:
sub_btn = tk.Button(root, text="Submit", command=Submit)
sub_btn.grid(row=2, column=0)
user_label.grid(row=0, column=0)
user_entry.grid(row=0, column=1)
pass_label.grid(row=1, column=0)
pass_entry.grid(row=1, column=1)
root.mainloop()
Current Result
Expected Result
The main problem here is the misunderstanding of how event driven programming works. The following line of code runs ONLY when the tkinter window is initially drawn.
if user_entry["text"] == "SecondName":
sub_btn = tk.Button(root, text="Close", command=Close)
else:
sub_btn = tk.Button(root, text="Submit", command=Submit)
Which means user_entry["text"] is never "SecondName". Furthermore, user_entry["text"] does not do what you expect it to be doing, it returns the name of the textvariable option and not the contents of the entry widget, what you need to do is change your function to use elif:
def Submit():
user = user_var.get()
passw = pass_var.get()
label_text = user_label["text"]
char = label_text.split()[0]
entries[char] = (user, passw)
if char == "FirstName":
user_label["text"] = "SecondName " + user_label["text"].split()[1]
pass_label["text"] = "SecondName " + pass_label["text"].split()[1]
elif char == "SecondName":
sub_btn.config(text='Close', command=Close) # Change button if `char` is "SecondName" only
user_var.set("")
pass_var.set("")
print(entries)
Side Note: To get the value inside the entry widget, you can use user_entry.get() or user_var.get()
How to disable the button in tkinter window when two passwords does not match?
My work:
from tkinter import *
from functools import partial
root = Tk()
root.geometry('280x100')
root.title('Tkinter Password')
def validation_pw(ep,cp):
if ep.get() == cp.get():
Label(root, text = "Confirmed").grid(column=0, row=5)
else:
Label(root, text = "Not matched").grid(column=0, row=5)
# check_button['state'] = DISABLED <============================
ep = StringVar()
cp = StringVar()
Label1 = Label(root, text = "Enter Password").grid(column=0, row=0)
pwEnty = Entry(root, textvariable = ep, show = '*').grid(column=1, row=0)
# Confirmed password label
Label2 = Label(root, text = "Confirm Password").grid(column=0, row=1)
pwconfEnty = Entry(root, textvariable = cp, show = '*').grid(column=1, row=1)
validation_pw = partial(validation_pw, ep,cp)
check_button = Button(root, text = "check", command = validation_pw).grid(column=0, row=4)
root.mainloop()
It shows if two passwords are not matched.
Now, I want to disable the check button if two passwords are not matched. I want the user cannot try the passwords anymore if failure.
So in the function validation_pw, I add check_button['state'] = DISABLED.
However, an error pops out
TypeError: 'NoneType' object does not support item assignment
How to fix this issue? Thanks!
Your checkbutton is actually None, because it's the result of the grid function.
To fix it, first declare the button, next grid it.
Before:
check_button = Button([...]).grid(column=0, row=4) # Result of Button.grid function
print(check_button) # None
After:
check_button = Button([...])
check_button.grid(column=0, row=4)
print(check_button) # Button object ...
You get the error of NoneType because at one point it was assigned nothing. This is because you used .grid on the same line as the button.
Fixed code:
check_button = Button(root, text = "check", command = validation_pw)
check_button.grid(column=0, row=4)
I am essentially trying to have my entry box display the entered text on the screen as a label, expect after each time the button is pressed (the button that displays the text), the newly entered data is displayed somewhere else on the screen. Essentially multiple labels from one entry box and button.
def writelabel():
labelentrval = Label(master, font = ("Helvetica", 15), text="" + str(entryvalue.get()))
labelentrval.place(x=645,y=621)
entryvalue.delete(first=0,last=22)
()
entryvalue = Entry(master)
entryvalue.place(x=700, y=515)
buttonpressy = Button(master,text="Enter", command=writelabel)
buttonpressy.place(x=845,y=510)
Code is above, and so far when I enter something into my entry box and press the button it displays it on the screen as a label. But how would I keep displaying my entries over and over in different places?
Thank you
You want to create a new label for every button press:
from tkinter import *
root = Tk()
def clicked():
text = e.get()
newLabel = Label(root, text=text)
newLabel.pack()
e = Entry(root)
e.pack()
b = Button(root, text='click', command=clicked)
b.pack()
root.mainloop()
I'm trying to create a factorial calculator GUI.
The program works fine, but the problem I'm having is that when there are too many numbers coming in from the output, the screen automatically increases in width. I've tried using tk.Text to create a limit to the size of the textbox and so the text continues to the next row when the columns are filled.
But when I had to input text in to the tk.Text it didn't work since the variable I used is being processed in the function that gets called when the button is pressed. I have tried googling this problem but I couldn't find anything, I did find some people explaining how to use variables that get created/processed inside of a function, but that didn't work so I think I have done something wrong in my code.
Note: I am using lambda to call my function (not sure if this is important or not).
TLDR: Text gets too long when too much information is outputted. tk.Text didn't work for me since I couldn't figure out how to use the variable that is created/processed inside of a function that is only called when the button is pressed.
Here is my entire code: https://pastebin.com/1MkdRjVE
Code for my function:
def start_calc():
output_array = ["placehold"]
start_text.set("Loading...")
i = 1
global e1
global e2
output_array.clear()
string = e1.get()
string2 = e2.get()
integr = int(string)
integr2 = int(string2)
if string == "":
error_message.set("Please enter correct numbers.")
elif string2 == "":
error_message.set("Please enter correct numbers.")
else:
while integr2 >= i:
calc = integr ** i
calcstr = (str(calc))
output_array.append(calcstr)
i += 1
start_text.set("Start!")
output_array_str = (', '.join(output_array))
output_msg.set("Output: " + output_array_str)
print(output_array_str) #This is just so I know if it's working or not in the terminal
Code for my output:
output_msg = tk.StringVar()
output_text = tk.Label(root, textvariable=output_msg, font="Raleway")
output_msg.set("Output: ")
output_text.grid(columnspan=3, column=0, row=14)
I think this is what you are looking for:
#Imports
import tkinter as tk
#Variables
root = tk.Tk()
#Tkinter GUI setup basic
canvas = tk.Canvas(root, width= 400, height=400)
canvas.grid(columnspan=3, rowspan=120)
#Title
text = tk.Label(root, text="Calculating factorials", font="Raleway")
text.grid(column=1, row=1)
#Function
def start_calc():
output_array = ["", ""]
start_text.set("Loading...")
i = 1
global e1
global e2
output_array.clear()
string = e1.get()
string2 = e2.get()
integr = int(string)
integr2 = int(string2)
if string == "":
error_message.set("Please enter correct numbers.")
elif string2 == "":
error_message.set("Please enter correct numbers.")
else:
while integr2 >= i:
calc = integr ** i
calcstr = (str(calc))
output_array.append(calcstr)
i += 1
start_text.set("Start!")
output_array_str = (', '.join(output_array))
# Change the output
output_text.config(state="normal")
# delete last output:
output_text.delete("0.0", "end")
# insert new output:
output_text.insert("end", output_array_str)
output_text.config(state="disabled")
print(output_array_str) #This is just so I know if it's working or not in the terminal
#input
tk.Label(root, text="Number :").grid(row=10)
tk.Label(root, text="Factorial :").grid(row=11)
e1 = tk.Entry(root)
e2 = tk.Entry(root)
e1.grid(row=10, column=1)
e2.grid(row=11, column=1)
#Error message if the input is invalid
error_message = tk.StringVar()
error_text = tk.Label(root, textvariable=error_message, font="Raleway")
error_message.set(" ")
error_text.grid(column=1, row=12)
#Startbutton
start_text = tk.StringVar()
start_btn = tk.Button(root, textvariable=start_text, command=start_calc, font="Raleway", bg="#20bebe", fg="white", height=2, width=15)
start_text.set("Start!")
start_btn.grid(column=1, row=13, pady=10)
#output
output_text = tk.Text(root, height=1, width=20, wrap="none", font="Raleway")
output_text.insert("end", "Output")
output_text.config(state="disabled")
output_text.grid(columnspan=3, column=0, row=14, sticky="news")
#Adding a scrollbar
scrollbar = tk.Scrollbar(root, orient="horizontal", command=output_text.xview)
scrollbar.grid(columnspan=3, column=0, row=15, sticky="news")
output_text.config(xscrollcommand=scrollbar.set)
#disclaimer message
disclaimer_text = tk.Label(root, text="Disclaimer: The factorials will be printed from 1 to the number you entered.")
disclaimer_text.grid(columnspan=3, column=0, row=110)
root.mainloop()
I used a <tkinter.Text> widget with wrap="none", height=1 and width=20 to make the output box. I disabled the entry so that the user can't change the results but can still copy it.
I have a simple GUI program using Tinter and Turtle where the goal is to draw a polygon. I ask the user for the number of sides and length of side. I made a simple GUI, but when I click the button to get the values I get very small decimal digit values and I can't figure out why.
import Tkinter as tk
def draw_polygon():
num_of_sides.get()
length_of_sides.get()
print num_of_sides, length_of_sides
root = tk.Tk()
tk.Label(root, text='Number of Sides').grid(row=0)
tk.Label(root, text='Length of Sides').grid(row=1)
num_of_sides = tk.Entry(root)
num_of_sides.grid(row=0, column=1)
length_of_sides = tk.Entry(root)
length_of_sides.grid(row=1, column=1)
draw_button = tk.Button(root, text='Draw', command=draw_polygon)
draw_button.grid(row=3, column=1)
tk.mainloop()
You must assign the return value of get() to a variable. Otherwise, you print the name of the widget, which by default is a point followed by a number.
import Tkinter as tk
root = tk.Tk()
tk.Label(root, text='Number of Sides').grid(row=0)
tk.Label(root, text='Length of Sides').grid(row=1)
num_of_sides = tk.Entry(root, name = "numOfSides")
num_of_sides.grid(row=0, column=1)
length_of_sides = tk.Entry(root, name = "lenOfSides")
length_of_sides.grid(row=1, column=1)
def draw_polygon():
ns = num_of_sides.get()
ls = length_of_sides.get()
print ns, ls
print num_of_sides, length_of_sides
draw_button = tk.Button(root, text='Draw', command=draw_polygon)
draw_button.grid(row=3, column=1)
tk.mainloop()
Of course, you may comment or remove the second print, I left it for the explanation. You may also remove the two name= arguments.