So here I have a program which first displays a information message and then you click next and it tells you to input your name before opening up the main window.
INFO ->(next) ENTER NAME ->(next)
When I enter my name in the entry box I want it to be checked that it does not contain 1.numbers and 2.is not blank. under the validate="key" option it means that once I start typing it validates. But rather I want it to only check the name once i press the NEXT button... If not it will open errorbox()
class errorbox():
def __init__(self):
windowError = Tk()
windowError.title("Error")
windowError.geometry('300x400')
error_message = Label(windowError, font=("Bold", 10), justify="left", text="Please enter a valid name")
def clicked1():
description.configure(text="Please enter your name")
nameBox = Entry(windowSplash, width=20, textvariable=name)
nameBox.place(rely=0.5, x=130, anchor=W)
reg = windowSplash.register(validate)
nameBox.config(validate="none",validatecommand=clicked2)
button2 = Button(text="Next", bg="white", width=5, command=lambda:[clicked2(),validate()])
button2.place(rely=0.5, x=300, anchor=E)
button1.destroy()
def validate(input):
if input.isdigit():
print("Invalid name was entered" + input)
errorbox()
return False
elif input is "":
print("No name entered")
errorbox()
return False
else:
return True
def clicked2():
print(name.get(), "logged in...")
windowSplash.destroy()
windowTool = Tk()
windowTool.title("Radial Measurements Calculator Tool")
windowTool.geometry('300x400')
name = StringVar()
windowSplash.mainloop()
Welcome to Stack Overflow Community.
I might have interpreted your question, but please make sure that next time you provide a minimal, reproducible example when you ask.
Here are a couple of things that I have observed.
The validate function takes input as a parameter, so make sure you pass that in the lambda function by lambda input = name.get(): [clicked2(),validate(input)].
By checking input.isdigit() does not guarantee that there might not be numbers after/between characters, so I suggest you to iterate through the string and check for isdigit()/type() or use re module. Also, an efficient way to check for empty string could be if not name.get():.
If you aim to open the new window only after the validation, I suggest you to call clicked2 from the validate function under a condition and not form the next button, because in this case your return form validate isn't used for anything.
Related
Here I've uploaded the entire code. The problem is on entering a non integer in the field, the program halts and it force quits. I tried solving it by using the part of code I've commented out. My solution doesn't work, so any guidance would be helpful.
from tkinter import *
root = Tk()
def sarteg():
**#while True:
# try:
# a= int(e.get())
# except ValueError:
# eror= Label(root,text="Please enter an integer").pack()
# continue
# else:
# break**
a= int(e.get())
if a%2==0:
even=Label(root,text="number is even").pack()
else:
odd=Label(root,text="number is odd").pack()
label1= Label(root, text="Enter an Integer then click on \"FIND OUT\"").pack()
e = Entry(root, width=20)
e.pack()
mybutt= Button(root, text="find out", command=sarteg)
mybutt.pack()
root.mainloop()
I tried the code, it seems to working fine.
You had error on line 5.
You added 2 asterisks.
**#while True:
If you remove the asterisks, it's working fine. Comments can be added by just adding # before the line.
One more thing I'd recommend it to create a common label to show the results. Because every time you check the number a new label appears creating a list of results.
I believe all you really have to do is remove the while True statement. Try this:
def sarteg():
try:
a = int(e.get())
except ValueError:
eror = Label(root, text="Please enter an integer").pack()
return None
if a % 2 == 0:
even = Label(root, text="number is even").pack()
else:
odd = Label(root, text="number is odd").pack()
Ultimately I want to make a small program with a text box where you have to type in the first 50 or so digits of Pi. What I want is for nothing to happen if the user types the correct characters, but I want something to flash red if they input the wrong character. For example, if the user types "3.1", nothing happens but the text showing up in the text box, but if they then type the wrong number, like "3.15", I want something to flash red.
from tkinter import *
def input(event):
inp = (ent.get('1.0', END))
if inp == '3':
print(inp)
else:
print(('--') + (inp))
root = Tk()
root.title('pi, okay')
root.geometry('425x50')
ent = Text(root, width = 50, height = 1)
ent.bind('<KeyRelease>', input)
ent.pack()
mainloop()
What I think SHOULD happen with this is for the console to print "3" IF the user inputs a "3", and for the console to print "--(whatever else the user would have typed)" if it is not a 3. But what actually happens is that the program will print "--(input)" no matter what.
You can use something like this if you need only one line of Input:
var = StringVar()
ent = Entry(root, width=50, textvariable=var)
def check_value(var, ent, *args):
pi = "3.1415"
if not pi.startswith(var.get()):
print("wrong input")
ent.config(fg="red")
else:
ent.config(fg="black")
var.trace('w', lambda *args: check_value(var, ent, *args))
ent.pack()
Here, var.trace() will call function check_value everytime when user types anything in Entry widget. You can add you logic there to verify the input value and change UI(or print logs) based on verification result.
In my program, the entry widget no longer validates after the delete command has been used on it - the idea is that if it meets a certain requirement, the text in the box is automatically deleted but continues to validate the input.
from tkinter import *
TEXT_TO_MATCH = 'APPLE'
def validate(userinput):
if userinput == TEXT_TO_MATCH:
print(True)
input_box.delete(0, END)
else:
print(False)
return True
window = Tk()
window.title('Delete after validation')
reg = window.register(validate)
input_box = Entry(window, validatecommand=(reg, '%P'), validate='all')
input_box.pack()
window.mainloop()
The entry widget automatically resets the validate option to "none" when you edit the entry widget from within the validation function.
You can re-enable the validation by using after_idle to reset the validate option after control has been returned to mainloop
def validate(userinput):
if userinput == TEXT_TO_MATCH:
input_box.delete(0, END)
input_box.after_idle(lambda: input_box.configure(validate="all"))
return True
To put it simply, a GUI button seems to be linked to the wrong function.
i have started to create a Vigenere cipher. A button that is meant to redirect to an encrypt function instead redirects to the decrypt function. W/ my current code it doesn't matter because the two codes are nearly the same but they will eventually have different uses and so need to be distinguished from each other.
i am unsure as to where the problem is so the whole code is attached.
from appJar import gui
app = gui("Vigenere Chipher")
app.addLabel("title", "Vigenere Chipher")
app.setBg("cyan")
app.setSize(600,400)
def press(Encrypt):
app.removeAllWidgets()
app.addLabel("title", "Encryption")
app.addEntry("Phrase")
app.setEntryDefault("Phrase", "Enter Phrase Here")
app.addEntry("Key")
app.setEntryDefault("Key", "Enter Key Here")
app.addLabel("RESULT", "This is your encrypted message: ")
def press(Submit):
phrase = app.getEntry("Phrase")
key = app.getEntry("Key")
def press(Back):
app.removeAllWidgets()
app.addLabel("title", "Vigenere Chipher")
app.setBg("cyan")
app.setSize(600,400)
app.addButtons(["Submit", "Back"], press)
def press(Decrypt):
app.removeAllWidgets()
app.addLabel("title", "Decryption")
app.addEntry("Phrase")
app.setEntryDefault("Phrase", "Enter Phrase Here")
app.addEntry("Key")
app.setEntryDefault("Key", "Enter Key Here")
phrase = app.getEntry("Phrase")
key = app.getEntry("Key")
app.addLabel("RESULT", "This is your decrypted message: ")
def press(Back):
app.removeAllWidgets()
app.addLabel("title", "Vigenere Chipher")
app.setBg("cyan")
app.setSize(600,420)
app.addButtons(["Encrypt", "Decrypt", "Close"], press)
app.addButtons(["Submit", "Back"], press)
app.addButtons(["Encrypt", "Decrypt", "Close"], press)
app.go()
Thankyou for your help
You've defined multiple functions with the same name press. Only the last definition will be used (the decrypting one), as it will replace the earlier definitions - this is not what you're intending.
You've then linked all buttons to this function.
So, the first thing you need to change, is to give each function its own name:
def encrypt()
...
def decrypt()
...
Then, you need to change how you've linked the buttons to the function.
You have two options:
1) Have a generic press function, that uses an IF statement on the button name, to determine the action:
def press(btn):
if btn == "Encrypt":
encrypt()
elif btn == "Decrypt":
decrypt()
elif btn == "Close":
app.stop()
app.addButtons(["Encrypt", "Decrypt", "Close"], press)
2) Directly link each button to the correct function.
app.addButtons(["Encrypt", "Decrypt", "Close"], [encrypt, decrypt, app.stop])
Later on, you'll come across the same issues with your Submit & Back buttons, and will need to use the same tactics...
I'm trying to make a log in program, but I can't get it to work.
When I'm running the code and type in the right Username and Password, it says wrong input.
import tkinter
window = tkinter.Tk()
window.title('LoginPage')
gebruikersnaam = 'Donald'
wachtwoord = 'Trump'
lblUsername = tkinter.Label(window,text='Username:')
lblUsername.pack(fill=tkinter.X)
entUsername = tkinter.Entry(window)
entUsername.pack(fill=tkinter.X)
lblPassword = tkinter.Label(window,text='Password:')
lblPassword.pack(fill=tkinter.X)
entPassword = tkinter.Entry(window)
entPassword.pack(fill=tkinter.X)
lblResult = tkinter.Label(window)
lblResult.pack(fil=tkinter.X)
def checkLogin(username,password):
if str(username) == gebruikersnaam and str(password) == wachtwoord:
lblResult.configure(text='Login was succesfull')
else:
lblResult.configure(text='Username or Password is wrong')
btn = tkinter.Button(window,text='Login',command= lambda x=entPassword.get(), y=entUsername.get():checkLogin(y,x))
btn.pack(fill=tkinter.X)
window.mainloop()
Right now, your code calls get() methods as soon as it runs, that's why you are getting empty values and "wrong input".
You need to make get() methods run after button click to give user some time to actually enter some values.
So you should pass Entrys as parameters and call get() methods inside of lambda.
btn = tkinter.Button(..., command=lambda x=entUsername, y=entPassword: checkLogin(x.get(), y.get()))
BUT, I think, instead of lambda, you should use a wrapper function, that calls checkLogin. Which makes your code easier to read and follow.
def wrapperCheck():
checkLogin(entUsername.get(), entPassword.get())
btn = tkinter.Button(window, text='Login', command=wrapperCheck)
btn.pack(fill=tkinter.X)
EDIT: Yet, even better approach is (thanks to comment from Bryan Oakley), remove parameters from your method and fetch those values inside of it.
def checkLogin():
username = entUsername.get()
password = entPassword.get()
#since get returns string objects you dont need str calls
if username == gebruikersnaam and password == wachtwoord:
lblResult.configure(text='Login was succesfull')
else:
lblResult.configure(text='Username or Password is wrong')
#also you can remove these temp values and directly compare like below
# entUsername.get() == gebruikersnaam and entPassword.get() == wachtwoord
btn = tkinter.Button(window,text='Login',command= checkLogin)