Python,Tkinter, making a username/password interface - python

Beginner to python. Can't seem to figure out how to set a password to these
entries.Looked into a bunch of sites already. Any examples or feedback is much appreciated.Thanks...............................................
from tkinter import*
from PIL import Image,ImageTk
import glob,os
root=Tk()
w1=Label(root,text="1")
w2=Label(root,text="2")
w3=Label(root,text="3")
e1=Entry(text="five")
e2=Entry(text="six")
e3=Entry(text="seven")
text=(e1)
def show_entry_fields():
print("1:%s\n2:%s\n3:%s" %(e1.get(),e2.get(),e3.get()))
e1.delete(0,END)
e2.delete(0,END)
e3.delete(0,END)
b1=Button(root,text="Submit",command=show_entry_fields).grid(row=3,column=3)
e1.grid(row=0,column=1)
e2.grid(row=1,column=1)
e3.grid(row=2,column=1)
w1.grid(row=0)
w2.grid(row=1)
w3.grid(row=2)
image=Image.open("beer.png")
photo=ImageTk.PhotoImage(image)
label=Label(image=photo)
label.image=photo#keep a reference
label.grid(column=4)
mainloop()

Can't seem to figure out how to set a password to these entries.
Going from your comment:
rather set a password to each entry.
This might be more along the lines of what you are attempting to do.
The below code will check if each entry field has the correct password.
if so it prints success and if not it prints try again.
from tkinter import *
root=Tk()
Label(root, text="1").grid(row=0)
Label(root, text="2").grid(row=1)
Label(root, text="3").grid(row=2)
e1=Entry(root)
e2=Entry(root)
e3=Entry(root)
e1.grid(row=0,column=1)
e2.grid(row=1,column=1)
e3.grid(row=2,column=1)
def test_entry_fields():
if e1.get() == "five" and e2.get() == "six" and e3.get() == "seven":
print("You have entered the correct passwords!")
else:
print("Please try again.")
e1.delete(0,END)
e2.delete(0,END)
e3.delete(0,END)
b1=Button(root,text="Submit",command=test_entry_fields).grid(row=3,column=3)
mainloop()

If you are trying to create a "mask" to cover the input of a password field, for example "Hunter2" becomes "*******" then use this.
show="*"
-> replacing * with whichever char you want to use as a mask.
for example, to use the second textbox you have as a password field.
e2=Entry(text="six", show="*")

Related

Python log screen bug

My tkinter log in screen app has a bug that is when i click the log in button it just show the error.
from tkinter import *
from tkinter import messagebox
login_page = Tk()
login_page.title("login_page")
login_page.geometry("250x110")
def check_pass():
if username == name and userpass == password:
print("this code works")
else :
messagebox.askretrycancel(title="Try again",message="Wrong password ")
# name and password entry
log_name = Entry(login_page)
log_name.grid(row=0, column=1, pady=15)
log_pass = Entry(login_page)
log_pass.grid(row=1, column=1, pady=5)
name_label = Label(login_page, text="Name here:- ")
name_label.grid(row=0, column=0, pady=15)
password_label = Label(login_page, text="Password:- ")
password_label.grid(row=1, column=0, pady=5)
# LOG IN BUTTON
login_btn = Button(login_page, text="LOG IN", command=check_pass)
login_btn.grid(row=2, column=0, columnspan=2, ipadx=100, padx=5)
username = log_name.get()
userpass = log_pass.get()
name = "admin"
password= "admin"
mainloop()
The problem is because the username and the password variables are in the main block and when you run the code the entry boxes are empty(initially) which assigns '' to the variables. So to overcome that you should assign the variables inside the function, where now the values of the filled entry box is only taken.
Code:
from tkinter import *
from tkinter import messagebox
login_page = Tk()
login_page.title("login_page")
login_page.geometry("250x110")
def check_pass():
username = log_name.get()
userpass = log_pass.get()
if username == name and userpass == password:
messagebox.showinfo('Successfull','Login successfull')
else:
choice = messagebox.askretrycancel("Try again","Wrong password ")
if choice == True:
pass
else:
login_page.destroy()
......
# ALL THE SAME LINES OF CODE TILL
name = "admin"
password = "admin"
login_page.mainloop()
Also since your using a messagebox like askretrycancel, you can do certain action based on the choice by the user. So here I have said if the user clicks on retry, then ask them to login again, or else close the application. You can change it to whatever you like(or even remove it too.)
And also it is recommended to say login_page.mainloop(), just so that tkinter isnt confused at any later steps.
Hope your "bug" is cleared and do let me know if any errors :D
Cheers

Is it possible to display python input statements in Tkinter?

I've python code that takes user input, hence I'm using lots of input statements. Now I'm creating GUI using Tkinter and want to display those input statements in Tkinter. Is there a way to to it?
For ex.
var=float(input("enter a number"))
Now I want to show the input statement "enter a number in Tkinter". Is it possible to do it? If yes, how?
Rather than using the input function, you could user tkinter's askstring command. This will bring up a small dialog box with the question asked and return the user's entry to the script.
import tkinter as tk
import tkinter.simpledialog as sd
def getUserInput():
userInput = sd.askstring('User Input','Enter your name')
print(f'You said {userInput}')
root = tk.Tk()
btn = tk.Button(root,text="Get Input", command=getUserInput)
btn.grid()
root.mainloop()
If you wish to ask for numerical values, tkinter also has askfloat and askinteger functions. These allow you to specify minimum and maximum values.
import tkinter as tk
import tkinter.simpledialog as sd
def getUserInput():
userInput = sd.askstring('User Input','Enter your name')
print(f'You said {userInput}')
def getUserFloatInput():
options = {'minvalue':3.0,'maxvalue':4.0}
userInput = sd.askfloat('User Input','Enter an approximation of Pi',**options)
print(f'You said pi is {userInput}')
def getUserIntegerInput():
options = {'minvalue':4,'maxvalue':120}
userInput = sd.askinteger('User Input','How old are you?',**options)
print(f'You said you are {userInput}')
root = tk.Tk()
btn1 = tk.Button(root,text="Get String Input", command=getUserInput)
btn1.grid()
btn2 = tk.Button(root,text="Get Float Input", command=getUserFloatInput)
btn2.grid()
btn3 = tk.Button(root,text="Get Integer Input", command=getUserIntegerInput)
btn3.grid()
root.mainloop()

code keeps on returning to a submit button for some reason

import Tkinter as tk
import os, time, smtplib
top = tk.Tk()
top.withdraw()
def pause(n):
time.sleep(n)
def clear():
os.system('cls')
def valueGET(val1, val2):
top.withdraw()
user = val1 + "#gmail.com"
pswd = val2
try:
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(user, pswd)
except smtplib.SMTPAuthenticationError:
print "Sorry, wrong password and/or username"
pause(1)
clear()
login()
print "sucess"
def login():
top.deiconify()
L1 = tk.Label(top, text="User Name")
L1.grid(row=0, column=0)
E1 = tk.Entry(top, bd = 5)
E1.grid(row=0, column=1)
L1 = tk.Label(top, text="Password")
L1.grid(row=1, column=0)
E2 = tk.Entry(top, bd = 5, show="*")
E2.grid(row=1, column=1)
submit = tk.Button(top, text="Submit", width=15, command=lambda: valueGET(E1.get(), E2.get()))
submit.grid(row=3, column=1)
top.mainloop()
def main():
print "Do you wish to proceed?"
cont = raw_input("> ").lower()
if cont[0] == "y":
clear()
login()
print "pass"
main()
pardon me for not describing the question accurately enough but I honestly cant think of another way of putting it. When I run the code it goes all the way through to valueGET() and if the user and pass is correct it should (i think break out of the try block - which it does because i put a basic print statement to test that. But then it goes straight to the login again and stops at the submit button (i ran it through visual studio to see where it was getting stuck and it looks like its there). SO anyways, if anyone could help clarify this it would be great... much thanks in advance
There are some problems. If I understand you right, you get into the except block and from there you call login() again. However you did not clear your top window. Should the window contain the login form twice? And you call the top.mainloop() in login() which causes the mainloop to be run a second time when you call login() the second time.
Try moving top.mainloop() outside login() (maybe into the main() function and do not recreate the contents of your window.

Python Tkinter project

I'm working on a final for python. My goal is to make a code that uses Tkinter to ask the user to input the answer to a math problem using an entry box then press submit. I want to be able to have python do something depending on whether the answer is right or wrong, but I'm not sure how to do this with Tkinter. How do I make it "check" the answer? For example,
ent = Entry(pyfinal)
btn = Button(pyfinal, text="Submit", bg="#000000")
lbl = Label(pyfinal, text="What is the answer to 5 x 5?")
If I was using regular python, I would do this,
ent = int(input('What is 5 x 5? '))
if ent == int ('25'):
print ("correct")
else:
print ("wrong, try again.")
How would I do that with Tkinter while keeping it all in the Tkinter window?
Thanks
Try using if statements for example:
Mp = Answer to math problem
Answer = What user wrote
If Mp == Answer:
Lbl = Label("You are right")
Lbl2.pack()
Lbl.after(3000, lambda: label.destroy())
Else:
Lbl2 = Label("You are wrong')
Lbl2.pack()
Lbl2.after(3000, lambda: label2.destroy())
Only write the .after statement if you want to delete this label in a certain amount of time

How can I make windows in Tkinter that run in succession? (Python 2.7.11)

I want to have a login window pop up at first, then once the conditions are satisfied, it closes the login window and opens a new window.
from Tkinter import *
import tkMessageBox
#Not really sure what i'm doing here anymore
while True:
Login = Tk()
Login.title('Login')
Login.geometry('400x130')
NameLabel = Label(Login, text='Username')
NameLabel.place(bordermode=OUTSIDE, height=25, width=100, x=100)
NameEntryRaw = Entry(Login)
NameEntryRaw.place(bordermode=OUTSIDE, height=25, width=100, x=200)
CodeLabel = Label(Login, text='Code')
CodeLabel.place(bordermode=OUTSIDE, height=25, width=100, x=100, y=30)
CodeEntryRaw = Entry(Login)
CodeEntryRaw.place(bordermode=OUTSIDE, height=25, width=100, x=200, y=30)
def tbd():
tkMessageBox.showinfo('Congrats!', 'This program is not done yet')
def login():
Usernames=list()
Usernames.append('Mordecai')
Usernames.append('Ezekiel')
Usernames.append('Goliath')
Usernames.append('Abraham')
Usernames.append('Bartholomew')
Usernames.append('Jedediah')
Usernames.append('Solomon')
Usernames.append('Tobias')
Usernames.append('Yohanan')
Usernames.append('Lucifer')
NameEntry=NameEntryRaw.get()
CodeEntry=CodeEntryRaw.get()
CodeReal='116987'
if Usernames.count(NameEntry) == 0:
tkMessageBox.showinfo('Error!', 'Your Username is invalid! Try Again.')
else:
()
if CodeEntry != CodeReal:
tkMessageBox.showinfo('Error!', 'The Code entered is invalid! Try Again.')
else:
()
LoginButton = Button(Login, text="Login", command=login)
LoginButton.place(bordermode=OUTSIDE, height=50, width=200, x=100, y=60)
Login.mainloop()
else:
DataBase = Tk()
#this will be the data base
DataBase.mainloop()
You don't want to use two mainloop's. Generally speaking, your tkinter app should have a single .mainloop called.
As for how to get the login popup and then switch to the window... You can create your root window with the app and when you start your program have a Toplevel window be shown with the login stuff, maybe hide / withdraw the root additionally?, have the toplevel have a submit button or something that would validate the credentials. If the credentials are valid, then you can use the destroy() method and remove the toplevel widget / go to the root window for your main app.
Having a while True repeat the process of creating a GUI + mainloop is bad for obvious reasons.
Edit: static is probably a bad term for a mutable object, since it's mutable... Added tuple vs list for global.
You don't need to create a blank list and then use append to add your usernames to the usernames list. You can make this global. Since, username is a mutable object (it's a list) you could still perform operations elsewhere in your code on this global, say .append etc. Or, if you never have these change i'd make it a tuple, since they're immutable and this "fits" better with the intent.
Instead of using .count(*) to get the occurrences of an element in a list you can just use:
if (object) in (some list) #Object is an abstraction, not the type
If CodeReal is static, which it looks to be, you can also make this global.
Here's a quick edit to your code, you can do this without classes, but I used classes here to try to distinctly show the logical separation in the program.
I changed a few variable names as well, so that it was easier to read / understand. I also used .pack() and .grid() as this was quicker to code than having to use .place() everywhere this is an arbitrary choice.
import Tkinter as tk
import tkMessageBox as messagebox
import sys
#No need to do usernames = list() and then .append for each one.
#Just make a global list holding them all...
USERNAMES = ('Mordecai', 'Ezekiel', 'Goliath', 'Abraham', 'Bartholomew',
'Jedediah', 'Solomon', 'Tobias', 'Yohanan', 'Lucifer')
PASSWORD = '116987' #Was CodeReal, this can be global
#We overrode the closing protocol here.
def closing_protocol():
if messagebox.askokcancel("Quit", "Do you want to quit?"):
sys.exit()
#A container for our Login "app".
class Login(tk.Toplevel):
def __init__(self, *args, **kwargs):
#We init the toplevel widget.
tk.Toplevel.__init__(self, *args, **kwargs)
#We set the closing protocol to be the overridden version / func.
self.wm_protocol("WM_DELETE_WINDOW", closing_protocol)
tk.Label(self, text='Username').grid(row=0, column=0)
self.username = tk.Entry(self)
self.username.grid(row=0, column=1)
tk.Label(self, text='Password').grid(row=1, column=0)
#Show = '*' just hides the password instead of plain-text like
#you typically see
self.password = tk.Entry(self, text='Password', show='*')
self.password.grid(row=1, column=1)
#When the button is clicked the _callback function will be called
tk.Button(self, text='Login', command=self._callback).\
grid(row=2, column=0, columnspan=2, sticky="nsew")
def _callback(self):
#If the username or password is bad, raise an error message.
if (self.username.get() not in USERNAMES or
self.password.get() != PASSWORD):
messagebox.showerror("Validation Error!",
"You have entered invalid credentials.\n" +
"Please try again.")
#otherwise, we're good to go. Destroy login / show main app.
else:
root.deiconify()
app.pack()
self.destroy()
class Main(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
tk.Label(self, text="MAIN APP STUFF").pack()
if __name__ == '__main__':
root = tk.Tk()
root.withdraw() #Hides the root window initially.
app = Main(root)
Login()
root.mainloop()
I want to thank you for clarifying what you did for me. It proved to be very helpful! Here is what I've settled with. I put the names back and made it to work without classes, as I found it a little too difficult to work with.
from Tkinter import *
import tkMessageBox
import sys
import binascii #Not for this part
Codenames = ['Mordecai', 'Ezekiel', 'Goliath', 'Abraham', 'Bartholomew',
'Jedediah', 'Solomon', 'Tobias', 'Yohanan', 'Lucifer']
Password = '116987'
def close_protocol():
if tkMessageBox.askokcancel("Quit", "Do you want to quit?"):
sys.exit()
#Below for a later part...
def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
bits = bin(int(binascii.hexlify(text.encode(encoding, errors)), 16))[2:]
return bits.zfill(8 * ((len(bits) + 7) // 8))
def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'):
n = int(bits, 2)
return int2bytes(n).decode(encoding, errors)
def int2bytes(i):
hex_string = '%x' % i
n = len(hex_string)
return binascii.unhexlify(hex_string.zfill(n + (n & 1)))
#Above for a later part...
SDB = Tk()
SDB.title("SMEGJALBYT DATA BASE")
SDB.withdraw()
SDBLogin = Toplevel()
SDBLogin.title("Login")
SDBLogin.wm_protocol("WM_DELETE_WINDOW", close_protocol)
CodenameLabel = Label(SDBLogin, text="Codename")
CodenameLabel.grid(row=0, column=0)
CodenameEntry = Entry(SDBLogin)
CodenameEntry.grid(row=0, column=2)
PasswordLabel = Label(SDBLogin, text="Password")
PasswordLabel.grid(row=1, column=0)
PasswordEntry = Entry(SDBLogin, show='*')
PasswordEntry.grid(row=1, column=2)
def login_operation():
if CodenameEntry.get() not in Codenames:
tkMessageBox.showinfo("INVALID CODENAME!", "Please verify input in the 'Codename' field")
elif PasswordEntry.get() != Password:
tkMessageBox.showinfo("INVALID PASSWORD!", "Please verify input in the 'Password' field")
else:
SDB.deiconify()
SDBLogin.destroy()
LoginButton = Button(SDBLogin, text="Login", command=login_operation)
LoginButton.grid(row=2, column=1)
#Code continues...
#Code finisles....
SDB.mainloop()
This has the same basic functionality, just organised the way I wanted it.

Categories