I'm trying to create a feedback form using Tkinter in Python. For now I am writing for it to show a message box if the name entry is '' when clicked on the submit button. But the button cannot be clicked and is disabled. How can I fix this?
# import all functions from the tkinter
from tkinter import *
from tkinter import messagebox
# import messagebox class from tkinter
from tkinter import messagebox
# Create a GUI window
root = Tk()
# create a function to check input
def check_input():
if name_input == '':
messagebox.showerror("please enter your name")
# create the input entry
name_input = Entry(root)
age_input = Entry(root)
phone_input = Entry(root)
email_input = Entry(root)
# label the input entry
name_label = Label(text="Username")
age_label = Label(text="Age")
phone_label = Label(text="Phone")
email_label = Label(text="Email")
# display the input entry
name_label.grid(row = 1,column = 1, padx = 10)
name_input.grid(row = 2,column = 1,padx = 10)
age_label.grid(row = 3,column = 1,padx = 10)
age_input.grid(row = 4,column = 1,padx = 10)
phone_label.grid(row = 5,column = 1,padx = 10)
phone_input.grid(row = 6,column = 1,padx = 10)
email_label.grid(row = 7,column = 1,padx = 10)
email_input.grid(row = 8,column = 1,padx = 10)
# create the submit button
submit_button = Button(root,text="Submit",command = check_input)
# display the submit button
submit_button.grid(row = 9,column = 1,padx = 10)
# Start the GUI
root.mainloop()
You have to use the get() method to get contents from an Entry:
# create a function to check input
def check_input():
if name_input.get() == '':
messagebox.showerror("please enter your name")
[![tested and shows no error][1]][1]
your button is clickable and is visible ... there maybe some other issue with your requirements but button works
[1]: https://i.stack.imgur.com/JQqH3.png
if you want to get value from the textbox your need to set text variable for entry
like
ttk.Entry(win,textvariable=hexanum).grid(column=1,row=0)
then if you need to get values from text box you'll be doing something like
inhexa=(hexanum.get()) #hexanum is the textvariable associated to entry/textbox
#inhexa is a variable in which the value from get function is stored (if need to store)
do your homework :) feel free to ask
Related
I like to mixed my radio button selection with a few user input boxes.
I managed to output them separately but I can't combine them due to the one using canvas1.pack and another using row.pack.
This is my first radio button interface where user will select Auto or Manual and there is a box for user to input stock symbols manually.
This interface by default will show the default parameters such as volume or dividend amount and the user can change this parameter.
When I tried to put them together, they overlaps. The stock symbol input box was also shifted down. How can I move the parameter boxes below the auto and manual radio button without shifting the stock symbol box to the bottom?
Below is a sample of my code that is ready to be executed on jupyter.
from tkinter import *
from tkinter import simpledialog
from tkinter import messagebox
import tkinter as tk
#default filter values
parameter1 = 100000
parameter2 = 3
global answer
global user_list
# Prepare parameters
fields = ['Min. parameter1', 'Min. parameter2', 'Min. 3parameter3',
'Min. parameter4','Min. parameter5', 'Max. parameter6']
default_values = [parameter1,parameter2,parameter3,parameter4,
parameter5,parameter6]
captured_values = []
def on_closing():
if messagebox.askokcancel("Quit", "Do you want to quit?"):
root.destroy()
sys.stdout = orig_stdout
f.close()
sys.exit("Application closed by user")
def makeform(root, fields,default_values):
entries = {}
for i in range(len(fields)):
row = tk.Frame(root)
lab = tk.Label(row, width=24, text=fields[i]+": ", anchor='w')
ent = tk.Entry(row)
ent.insert(0, default_values[i])
row.pack(side=tk.TOP,
fill=tk.X,
padx=5,
pady=5)
lab.pack(side=tk.LEFT)
ent.pack(side=tk.RIGHT,
expand=tk.YES,
fill=tk.X)
entries[fields[i]] = ent
return entries
# Button click event
def btn_click (e):
global answer
answer_choice = rdo_var.get()
answer = rdo_txt[answer_choice]
global user_list
user_list = entry1.get()
captured_values.append(e['Min. parameter1'].get())
captured_values.append(e['Min. parameter2'].get())
captured_values.append(e['Min. parameter3'].get())
captured_values.append(e['Min. parameter4'].get())
captured_values.append(e['Min. parameter5'].get())
captured_values.append(e['Max. parameter6'].get())
root.destroy()
return answer
# Generate Tk class
root = tk.Tk()
# Screen size
root.geometry ('270x250')
# Screen title
root.title ('Enter parameters')
# set default parameters
ents = makeform(root, fields, default_values)
# box for manual input
canvas1 = tk.Canvas(root, width = 350, height = 400)
canvas1.pack()
entry1 = tk.Entry (root)
canvas1.create_window(165, 45, window=entry1)
# List radio button labels
rdo_txt = ['Auto','Manual']
# Radio button status
rdo_var = tk.IntVar ()
# Create and place radio buttons dynamically
for i in range (len (rdo_txt)):
rdo = Radiobutton (root, value = i, variable = rdo_var, text = rdo_txt [i])
rdo.place (x = 20, y = 15 + (i * 20))
# Create button
confirm_button = tk.Button (root, text = 'Confirm', command = (lambda e=ents: btn_click(e)))
confirm_button.place (x = 180, y = 200)
root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop ()
if(answer == 'Manual'):
print('Manual run selected.')
manual_run = 1
temp_user_list = []
user_list = user_list.split(',')
for i in range(len(user_list)):
temp_user_list.append(user_list[i].strip().upper())
print('Symbol(s) entered : ' + str(temp_user_list))
else:
manual_run = 0
print('Auto run selected.')
# new captured values
parameter1 = float(captured_values[0])
parameter2 = float(captured_values[1])
Here is an expanded answer.
Complete code example.
from tkinter import *
from tkinter import simpledialog
from tkinter import messagebox
import tkinter as tk
#default filter values
parameter1 = 100000
parameter2 = 2
parameter3 = 3
parameter4 = 4
parameter5 = 5
parameter6 = 6
global answer
global user_list
# Prepare parameters
fields = ['Min. parameter1', 'Min. parameter2', 'Min. parameter3',
'Min. parameter4','Min. parameter5', 'Max. parameter6']
default_values = [parameter1,parameter2,parameter3,parameter4,
parameter5,parameter6]
captured_values = []
def on_closing():
if messagebox.askokcancel("Quit", "Do you want to quit?"):
root.destroy()
sys.stdout = orig_stdout
f.close()
sys.exit("Application closed by user")
def makeform(root, fields,default_values):
entries = {}
for i in range(len(fields)):
row = tk.Frame(root)
lab = tk.Label(row, width=28, text=fields[i]+": ", anchor='e')
ent = tk.Entry(row)
ent.insert(0, default_values[i])
row.pack(side=tk.TOP,
fill=tk.X,
padx=5,
pady=5)
lab.pack(side=tk.LEFT)
ent.pack(side=tk.RIGHT,
expand=tk.YES,
fill=tk.X)
entries[fields[i]] = ent
return entries
# Button click event
def btn_click (e):
global answer
answer_choice = rdo_var.get()
answer = rdo_txt[answer_choice]
global user_list
user_list = entry1.get()
captured_values.append(e['Min. parameter1'].get())
captured_values.append(e['Min. parameter2'].get())
captured_values.append(e['Min. parameter3'].get())
captured_values.append(e['Min. parameter4'].get())
captured_values.append(e['Min. parameter5'].get())
captured_values.append(e['Max. parameter6'].get())
root.destroy()
return answer
# Generate Tk class
root = tk.Tk()
# Screen size
root.geometry("410x260")
# Screen title
root.title('Enter parameters')
# set default parameters
ents = makeform(root, fields, default_values)
# box for manual input
manual = makeform(root, ['Manual input'], ["Enter value here"])
entry1 = manual["Manual input"]
entry1["background"] = "yellow" # make it standout
del manual
# List radio button labels
rdo_txt = ['Auto','Manual']
# Radio button status
rdo_var = tk.IntVar()
# Create and place radio buttons dynamically
for i in range (len (rdo_txt)):
rdo = Radiobutton (root, value = i, variable = rdo_var, text = rdo_txt [i])
rdo.place (x = 20, y = 15 + (i * 20))
# Create button
confirm_button = tk.Button (root, text = 'Confirm', command = (lambda e=ents: btn_click(e)))
confirm_button.place (x = 205, y = 220)
root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()
if(answer == 'Manual'):
print('Manual run selected.')
manual_run = 1
temp_user_list = []
user_list = user_list.split(',')
for i in range(len(user_list)):
temp_user_list.append(user_list[i].strip().upper())
print('Symbol(s) entered : ' + str(temp_user_list))
else:
manual_run = 0
print('Auto run selected.')
# new captured values
parameter1 = float(captured_values[0])
parameter2 = float(captured_values[1])
I have a program (below) that creates an entry box that shows only '*' when you type in it and it creates a button next to the text box. I want the button to show what has been typed in the entry box while it is being pressed. I have tried to use <Button-1> and <ButtonRelease-1> but to no avail.
import tkinter as tk
def myFunc() :
#Something#
pass
root = tk.Tk()
root.title('Password')
password = tk.Entry(root, show = '*')
password.grid(row = 0, column = 1)
password_label = tk.Label(text = 'Password:')
password_label.grid(row = 0, column = 0)
button = tk.Button(text = '.', command = myFunc)
button.grid(row = 0, column = 2)
Try this:
import tkinter as tk
def show_stars(event):
password.config(show="*")
def show_chars(event):
password.config(show="")
root = tk.Tk()
root.title("Password")
password = tk.Entry(root, show="*")
password.grid(row=0, column=1)
password_label = tk.Label(text="Password:")
password_label.grid(row = 0, column=0)
button = tk.Button(text="Show password")
button.grid(row=0, column=2)
button.bind("<ButtonPress-1>", show_chars)
button.bind("<ButtonRelease-1>", show_stars)
Using the bindings that #BryanOakley suggested
Only if button is pressed it changes the text from * to the text entered.
import tkinter as tk
def myFunc():
#Something#
if password.cget("show")=="*":
password.configure(show="")
elif password.cget("show") =="":
password.configure(show="*")
root = tk.Tk()
root.title('Password')
password = tk.Entry(root, show = '*')
p = password
password.grid(row = 0, column = 1)
password_label = tk.Label(text = 'Password:')
password_label.grid(row = 0, column = 0)
button = tk.Button(text = '.', command = myFunc)
button.grid(row = 0, column = 2)
root.mainloop()
I am using Tkinter to make a user input form and take values from users and storing the values in a database when clicked on the submit button. I want to clear all the fields from the entry widgets after clicking the submit button so that the values get stored in the database as well as the entry widgets clear out so that the user can again fill the details. I tried the delete(0;'end') command but it did not work.
Following is my code:
def database():
customer_name = name.get()
mobile_no = num.get()
email_id = mail_id.get()
address = addr.get()
result = {
"Customer Name":customer_name,
"Mobile":mobile_no,
"Email ID":email_id,
"Address":address
}
print(result)
db.Customer_Info.insert_one(result)
print('Value Inserted')
client.close()
##Creating tkinter window
def main_page():
global window
window = Tk()
window.title('Products')
window.geometry('400x500')
global name,uname,mob,num,mail_id,addr
name = StringVar()
num = IntVar()
num.set('')
mail_id = StringVar()
addr = StringVar()
Label(window,text = 'HN Organics',background = 'green',
foreground = 'white',font = ('Arial',20)).grid(column = 0,
row = 0, padx = 120, pady =25)
Label(window ,text = "Name").grid()
uname = Entry(window,textvariable = name).grid()
Label(window ,text = "Mobile No.").grid()
mob = Entry(window,textvariable = num).grid()
Label(window ,text = "Email ID").grid()
mail = Entry(window,textvariable = mail_id).grid()
Label(window ,text = "Address").grid()
addr1 = Entry(window,textvariable = addr).grid()
Button(window,text = 'Submit',command = database).grid()
window.mainloop()
main_page()
When the submit button is clicked the values are stored in the database but I want the entries to clear as well after being stored in the database. How do I do that??
I tried using name.delete(0.'end') / name.delete(0.'END') and even name.delete(0.'Tkinter.END') but it shows that there is no attribute delete.
You can add the set('') command in the database function after you store the values and it will clear out the entries so that the user can fill details again.
Just add:
name.set('')
num.set('')
mail_id.set('')
addr.set('')
after client.close()
Don't put quotations around END.
try name.delete (0, END).
Delete is part of normal tkinter library so should work.
I'm wondering if I got my if else statement wrong or if its a tkinter issue. I want it so that if a 0 is left in any or all boxes, it gives an error message. But after the error message is closed, it opens a random blank window. This is my code. The specific area is the if else statement within the function valueget()
import tkinter as tk
def mainwindow():
mainwindow = tk.Tk()
mainwindow.title('Enter values')
mainwindow.geometry('160x110')
mainwindow.config(bg='#aaf0d1')
tk.Label(mainwindow, text = 'Enter a', font = ('verdana'), bg='#aaf0d1').grid(row=0)
tk.Label(mainwindow, text = 'Enter b', font = ('verdana'), bg='#aaf0d1').grid(row=1)
tk.Label(mainwindow, text = 'Enter c', font = ('verdana'), bg='#aaf0d1').grid(row=2)
getA = tk.IntVar()
aBox = tk.Entry(mainwindow, textvariable = getA, width=3, bg='#aaf0d1')
aBox.grid(row=0, column=1)
aBox.config(highlightbackground='#aaf0d1')
getB = tk.IntVar()
bBox = tk.Entry(mainwindow, textvariable = getB, width=3, bg='#aaf0d1')
bBox.grid(row=1, column=1)
bBox.config(highlightbackground='#aaf0d1')
getC = tk.IntVar()
cBox = tk.Entry(mainwindow, textvariable = getC, width=3, bg='#aaf0d1')
cBox.grid(row=2, column=1)
cBox.config(highlightbackground='#aaf0d1')
button = tk.Button(mainwindow, text='Obtain roots', command = lambda: valueget(), font = ('verdana'), highlightbackground='#aaf0d1')
button.grid(row=4)
button.config(bg='#aaf0d1')
def valueget():
readA = getA.get()
readB = getB.get()
readC = getC.get()
intA = int(readA)
intB = int(readB)
intC = int(readC)
negroot = (readB**2)-(4*readA*readC)
quadformulaplus = (-readB + (pow(negroot,0.5)))/(2*readA) #quad forumla
quadformulaminus = (-readB - (pow(negroot,0.5)))/(2*readA) #quad forumla
messagewindow = tk.Tk()
messagewindow.geometry('290x50')
messagewindow.title('Roots of the equation')
messagewindow.config(bg='#aaf0d1')
if readA == 0 or readB==0 or readC==0 or (readA==0 and readB==0 and readC==0):
errorwindow = tk.messagebox.showerror(message='none').pack()
else:
label = tk.Label(messagewindow, text = f'The roots are {quadformulaplus:.1f} and {quadformulaminus:.1f}', bg='#aaf0d1', font = ('verdana'))
label.grid(row=1)
closebutton = tk.Button(messagewindow, text='Close', command = lambda: messagewindow.destroy(), font = ('verdana'), highlightbackground='#aaf0d1')
closebutton.grid(row=2)
closebutton.config(bg='#aaf0d1')
messagewindow.mainloop()
# print(f'the roots are {quadformulaplus:.1f} and {quadformulaminus:.1f}')
mainwindow.mainloop()
def startup():
startpage = tk.Tk()
startpage.title('Solver')
photo = tk.PhotoImage(file = r"/Users/isa/Desktop/DiffEqns/cover.png") #image load
coverbutton = tk.Button(startpage, image = photo, command = lambda: [startpage.destroy(), mainwindow()])
coverbutton.pack()
coverbutton.configure(highlightbackground='#aaf0d1')
startpage.mainloop()
startup()
Here's a basic idea of what I would do:
import tkinter as tk
from tkinter import messagebox
def mainwindow(root):
# Creates a toplevel window
mainwindow = tk.Toplevel()
mainwindow.protocol("WM_DELETE_WINDOW", root.destroy) # This overrides the "X" being clicked to also destroy the root window.
root.withdraw() # "Hides" the root window, leaving it (and mainloop) running in the background.
mainwindow.title('Enter values')
mainwindow.geometry('160x110')
mainwindow.config(bg='#aaf0d1')
# Since all three of the labels/entries are the same
# we can save space by generating them in a loop
entry_items = ('Enter a', 'Enter b', 'Enter c')
values = []
for x, item in enumerate(entry_items): # Using enumerate and x to assign rows
tk.Label(mainwindow, text = item,
font = ('verdana'), bg='#aaf0d1').grid(row=x) # Row assigned to x.
values.append(tk.StringVar()) # Appended StringVar to list.
tk.Entry(mainwindow,
textvariable = values[-1], # Uses the last value appended to the values list.
highlightbackground='#aaf0d1',
width=3,
bg='#aaf0d1').grid(row=x, column=1) # Row assigned to x.
tk.Button(mainwindow,
text='Obtain roots',
command = lambda vals = values: valueget(vals), # Here the button command is assigned with the values list
font = ('verdana'), bg='#aaf0d1',
highlightbackground='#aaf0d1').grid(row=3) # we know there are 3 items before this.
mainwindow.lift() # This is a method of bringing a window to the front
def valueget(vals):
# This line gets the values from the StringVars, converts them to ints,
# and returns them to their respective variables.
try:
readA, readB, readC = [int(val.get()) for val in vals]
except ValueError:
messagebox.showerror(title="Number Error", message='Values must be numbers')
return
# Here the variables are checked to see if they are 0
# Since each one is being checked if it is 0, there is no need to check if they are all 0.
for val in (readA, readB, readC):
if val == 0:
# If they are 0, shows an error message
messagebox.showerror(title="Zero Error", message='Values must not be zero')
return
# Creates a toplevel to display the results
messagewindow = tk.Toplevel()
messagewindow.title('Roots of the equation')
messagewindow.config(bg='#aaf0d1')
negroot = (readB**2)-(4*readA*readC)
quadformulaplus = (-readB + (pow(negroot,0.5)))/(2*readA) #quad forumla
quadformulaminus = (-readB - (pow(negroot,0.5)))/(2*readA) #quad forumla
tk.Label(messagewindow,
text = f'The roots are {quadformulaplus:.1f} and {quadformulaminus:.1f}',
bg='#aaf0d1',
font = ('verdana')).pack(padx = 5, pady = 2)
tk.Button(messagewindow,
text='Close',
command = messagewindow.destroy, # There is no need for a lambda for this.
font = ('verdana'),
bg = '#aaf0d1',
highlightbackground='#aaf0d1').pack(padx = 5, pady = 2)
# print(f'the roots are {quadformulaplus:.1f} and {quadformulaminus:.1f}')
messagewindow.lift() # This is a method of bringing a window to the front
def startup():
startpage = tk.Tk()
startpage.title('Solver')
# COMMENTED OUT FOR TESTING
#photo = tk.PhotoImage(file = r"/Users/isa/Desktop/DiffEqns/cover.png") #image load
coverbutton = tk.Button(startpage,
# COMMENTED OUT FOR TESTING
#image = photo,
text = "TESTING", # HERE FOR TESTING
highlightbackground='#aaf0d1',
command = lambda root = startpage: mainwindow(root)).pack() # Passes the startpage to the mainwindow function.
startpage.mainloop() # The only mainloop you need.
startup()
I would recommend to improve the readability of the if-else statement for a start.
coefficients = [readA, readB, readC]
if sum(coefficients): # If they all are all zeros this will be False
if min(coefficients): # If any one is zero, this will be False
label = tk.Label(messagewindow, text = f'The roots are {quadformulaplus:.1f} and {quadformulaminus:.1f}', bg='#aaf0d1', font = ('verdana'))
label.grid(row=1)
closebutton = tk.Button(messagewindow, text='Close', command = lambda: messagewindow.destroy(), font = ('verdana'), highlightbackground='#aaf0d1')
closebutton.grid(row=2)
closebutton.config(bg='#aaf0d1')
else:
errorwindow = tk.messagebox.showerror(message='none').pack()
else:
errorwindow = tk.messagebox.showerror(message='none').pack()
I'm using Tkinter to create a window with an entry field and a button. When the button is pressed and a certain condition is not met, I need my_label2 to show a specific text, in this case 'Not Valid'. Otherwise, I need the my_label2 to be blank. I have the variable label_text inside a function that is called by the button press, but I get an error saying that label_text is not defined. Can someone help me out with this?
root = tk.Tk()
def my_function():
valid = #this variable is either true or false
if valid :
label_text = ''
else :
label_text = 'Not Valid'
my_label = tk.Label(root, text = "Enter text: ")
my_label.grid(row = 0, column = 0)
my_entry = tk.Entry(root)
my_entry.grid(row = 0, column = 1)
my_button = tk.Button(root, text = "Submit", command = my_function)
my_button.grid(row = 1, column = 1)
my_label2 = tk.Label(root, textvariable = label_text)
my_label2.grid(row = 2, column = 1)
root.mainloop()
Tkinter Variables are different from normal variables. To create one:
label_text = tk.StringVar()
Then, rather than assigning to the variable, you nee to use the set method:
label_text.set('')
or
label_text.set('Not Valid')
See: http://effbot.org/tkinterbook/variable.htm