Working on a group program that has users and passwords. We are trying to insert our users and passwords via python to sqlite. But atm we are only sending blank data before our graphic window pops up with a button that is supposed to send the data. We have tried different variations found on multiple websites but nothing seems to work.
from tkinter import *
import sqlite3
import sys
conn = sqlite3.connect('indexCards.db')
cur = conn.cursor()
users ={}
def addUser(entUsername, entPassword):
#global entUsername, entPassword
NAME = entUsername.get()
PASSWORD = entPassword.get()
print("add User") #this is testing only
print(NAME, PASSWORD) # this is testing to see the passed variable
//
//This is where we are having the issues
conn.executemany('INSERT INTO USER(NAME,PASSWORD)\
VALUES (? ,?);', [(NAME,PASSWORD)])
conn.commit();
return (NAME, PASSWORD)
def makeWindow():
global entUsername, entPassword
window = Tk()
window.title('Add New User')
lblInst = Label(window, text = "Create your account here:", font=("Helvetica",16))
lblInst.pack()
lblUsername = Label(window, text="Please enter a username: ")
entUsername = Entry(window)
lblUsername.pack()
entUsername.pack()
lblPassword = Label(window, text="Please enter a password: ")
entPassword = Entry(window)
lblPassword.pack()
entPassword.pack()
btn = Button(window, text="Create", command=addUser(entUsername, entPassword))
btn.pack()
print (addUser(entUsername, entPassword))
print('entUsername', 'entPassword')
#window.mainloop()
return window
#if __name__ == '__main__':
# main():
window = makeWindow()
window.mainloop()
The problem is that you're calling the function immediately, before the user has a chance to enter any data.
See Why is Button parameter “command” executed when declared?
The reason it invokes the method immediately and pressing the button does nothing is that addUser(entUsername, entPassword) is evaluated and its return value is attributed as the command for the button. So if addUser prints something to tell you it has run and returns None, you just run addUser to evaluate its return value and given None as the command for the button.
To have buttons to call functions with different arguments you can use global variables, although I can't recommend it:
import sqlite3
from tkinter import *
conn = sqlite3.connect('indexCards.db')
cur = conn.cursor()
users = {}
cur = conn.cursor()
cur.execute('''
Create table if not exists USER(NAME varchar(100), PASSWORD varchar(100))
''')
def addUser():
NAME = entUsername.get()
PASSWORD = entPassword.get()
print("add User") # this is testing only
print(NAME, PASSWORD) # this is testing to see the passed variable
# This is where we are having the issues
conn.executemany('INSERT INTO USER(NAME,PASSWORD) VALUES (? ,?);', [(NAME, PASSWORD)])
conn.commit()
return (NAME, PASSWORD)
def makeWindow():
global entUsername
global entPassword
window = Tk()
window.title('Add New User')
lblInst = Label(window, text="Create your account here:", font=("Helvetica", 16))
lblInst.pack()
lblUsername = Label(window, text="Please enter a username: ")
entUsername = Entry(window)
lblUsername.pack()
entUsername.pack()
lblPassword = Label(window, text="Please enter a password: ")
entPassword = Entry(window)
lblPassword.pack()
entPassword.pack()
btn = Button(window, text="Create", command=addUser)
btn.pack()
print(addUser())
window.mainloop()
return window
window = makeWindow()
If you don't want to create global then you can pass the function with multiple arguments to an anonymous function i.e lambda function
btn = Button(window, text="Create", command= lambda : addUser(entUsername, entPassword))
Related
I'm trying to build my first app using python and tkinter.
I'm stuck where I can't run the content from another class into the same first window.
The first window is a login window, here is the full code of the class:
import tkinter as tk
import sqlite3
from tkinter import *
from gamecontent import Gamecontent
class MainApp(Tk):
def __init__(self):
Tk.__init__(self)
self.title('Word Warrior - Sign In')
self.geometry("650x510")
self.resizable(width=False, height=False)
# Create widgets
self.label_username = tk.Label(self, text="Username")
self.label_password = tk.Label(self, text="Password")
self.entry_username = tk.Entry(self)
self.entry_password = tk.Entry(self, show="*")
self.button_login = tk.Button(self, text="Login", command=self.login)
self.button_createacc = tk.Button(self, text="Create Account", command=self.createacc)
# Place widgets
self.label_username.place(x=200, y=150)
self.label_password.place(x=200, y=200)
self.entry_username.place(x=280, y=152, width=140, height=27)
self.entry_password.place(x=280, y=202, width=140, height=27)
self.button_login.place(x=280, y=242, width=140, height=27)
self.button_createacc.place(x=280, y=282, width=140, height=27)
# Create database and tables and cursor object
self.conn = sqlite3.connect('users.db')
self.c = self.conn.cursor()
self.c.execute("CREATE TABLE IF NOT EXISTS users (username text UNIQUE, password text)")
self.conn.commit()
self.conn.close()
def clear_content(self):
for widget in self.winfo_children():
widget.destroy()
def login(self):
# Get the username and password from the entry widgets
username = self.entry_username.get()
password = self.entry_password.get()
# Fetch username and password from the database
conn = sqlite3.connect('users.db')
c = conn.cursor()
c.execute("SELECT * FROM users WHERE username=? AND password=?", (username, password))
result = c.fetchone()
conn.close()
# Check if the username and password are correct
if result:
# If the login is successful, open a new window with the flashcard game
self.clear_content()
Gamecontent()
else:
# If the login is not successful, display an error message
self.label_message = tk.Label(self, text=" Wrong credentials ")
self.label_message.place(x=285, y=322)
def createacc(self):
# Get the username and password from the entry widgets
username = self.entry_username.get()
password = self.entry_password.get()
# Checks if user is entering an empty username/password while creating
if username == "" or password == "":
self.label_message = tk.Label(self, text=" Can't be empty ")
self.label_message.place(x=290, y=322)
else:
# Connect to the database (or create it if it doesn't exist)
conn = sqlite3.connect('users.db')
c = conn.cursor()
# Create the table if it doesn't exist
c.execute('''CREATE TABLE IF NOT EXISTS users
(username text, password text)''')
# Checks if an account with the same username exists
c.execute("SELECT * FROM users WHERE username = ?", (username,))
if c.fetchone() is None:
c.execute("INSERT INTO users VALUES (?, ?)", (username, password))
conn.commit()
self.label_message = tk.Label(self, text=" Account created ")
self.label_message.place(x=290, y=322)
else:
self.label_message = tk.Label(self, text=" Username exists ")
self.label_message.place(x=290, y=322)
# Close the connection
conn.close()
app = MainApp()
app.mainloop()
The change must be done when the login is correct, exactly in
self.clear_content()
Gamecontent()
The problem is that Gamecontent opens in another window and not into the same window.
Here is the code for Gamecontent class
from tkinter import *
from random import randint
from gamedata import words, count
class Gamecontent(Tk):
def __init__(self):
Tk.__init__(self)
self.title('Word Warrior - Play')
self.geometry("650x510")
self.resizable(width=False, height=False)
def next():
global hinter, hinter_count
# Clear the screen
answer_label.config(text="")
my_entry.delete(0, END)
hint_label.config(text="")
# Reset Hint stuff
hinter = ""
hinter_count = 0
# Create random selection
global random_word
random_word = randint(0, count-1)
# update label with Spanish Word
spanish_word.config(text=words[random_word][0])
def answer():
if my_entry.get().capitalize() == words[random_word][1]:
answer_label.config(text=f"Correct! {words[random_word][0]} is {words[random_word][1]}")
else:
answer_label.config(text=f"Incorrect! {words[random_word][0]} is not {my_entry.get().capitalize()}")
def hint():
global hinter_count
global hinter
if hinter_count < len(words[random_word][1]):
hinter = hinter + words[random_word][1][hinter_count]
hint_label.config(text=hinter)
hinter_count +=1
# Labels
spanish_word = Label(self, text="", font=("Helvetica", 36))
spanish_word.pack(pady=50)
answer_label = Label(self, text="")
answer_label.pack(pady=20)
my_entry = Entry(self, font=("Helvetica", 18))
my_entry.pack(pady=20)
# Create Buttons
button_frame = Frame(self)
button_frame.pack(pady=20)
answer_button = Button(button_frame, text="Answer", command=answer)
answer_button.grid(row=0, column=0, padx=20)
next_button = Button(button_frame, text="Next", command=next)
next_button.grid(row=0, column=1)
hint_button = Button(button_frame, text="Hint", command=hint)
hint_button.grid(row=0, column=2, padx=20)
# Create Hint Label
hint_label = Label(self, text="")
hint_label.pack(pady=15)
# Run next function when program starts
next()
self.mainloop()
I'm stuck with this for a while and can't move forward, I'm not even sure it's possible with tkinter to do so.
I tried clearing the content of the window and start an instance of the second class but it opens in another window.
Change
self.clear_content()
Gamecontent()
to
self.clear_content()
Gamecontent(self)
In gamecontent itself change
class Gamecontent(Tk):
def __init__(self):
Tk.__init__(self)
self.title('Word Warrior - Play')
self.geometry("650x510")
self.resizable(width=False, height=False)
to
class Gamecontent(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
#self.config(bg="white")
self.pack(fill=BOTH, expand=True)
parent.title('Word Warrior - Play')
This makes gamecontent to a frame which packs itself into your main app
Here is where I believe I would put the code for the restrictions
def savePassword():
os.system("Email.py")
if txt.get() == txt1.get():
# encode password for hashing
hashedPassword = hashPassword(txt.get().encode("utf-8"))
# insert masterpassword into database
insert_password = """INSERT INTO masterpassword(password)
VALUES(?) """
cursor.execute(insert_password, [hashedPassword])
sql_command = 'INSERT INTO details (email) VALUES(?) ' # Query
email = txt3.get()
cursor.execute(sql_command, [email])
db.commit()
passwordVault()
else:
lbl2.config(text="Passwords do not match")
i'd like it so that if the password does not reach a length requirement of say 7
Entry widget has validate and validatecommand that can do this job.
Here's an example code:
from tkinter import *
def check(ch):
return len(ch) <= 7 or ch==''
root = Tk()
ent = Entry(root, show='*')
ent.config(validate='key', validatecommand=(root.register(check), "%P"))
ent.pack()
root.mainloop()
update:
from tkinter import *
def savePasswd():
if len(ent.get())>7:
label['text'] = 'saved'
print("saved") # write save stmts here
else:
label['text']="Minimum length 7"
root = Tk()
label = Label(root)
label.pack()
ent = Entry(root, show='*')
ent.pack()
Button(root, text='save password', command=savePasswd).pack()
root.mainloop()
I've got a module that I'm calling a function to return a list of credential data. The code works in plain python3 but when running in tkinter, fails to get a value until I close the tkinter dialog and then it processes the remainder of the function as normal - except my program has been closed now. I've traced everything to the return from dbconnect.py. Any pointers would be appreciated. Thanks!
Edit:
Added login() function. note function within function. Never actually exits login(). last output comes from the subfunction userinfo(). Seems to stop there until original calling dialog closes, then completes last called function in main program successfully.
Local script call:
import dbconnect
array = dbconnect.getcredentials()
dbconnect.py module
dbconnect has related functions that work together to get the user log in and return a list.
def getcredentials(): # call from other scripts for connection setup.
credentials = []
for item in sys.argv:
credentials.append(item.strip("[,]"))
credentials.pop(0)
print("getcredentials(): items in argv after pop: ", credentials)
if credentials:
return(credentials)
else:
print("credentials not inialized!.def login():
# Create logwin window
logwin = Toplevel()
logwin.title("Log In")
# Called by login() GUI/bsubmit - returns credentials from log in GUI
def userinfo():
global array
# array = []
sname=serventry.get()
lname=lnentry.get()
pname=passentry.get()
array = [sname, lname, pname]
logwin.destroy()
print("userinfo() = ", array)
return array
# Called by login() GUI/ enter key from log in GUI
def userinfoalt(event): # event parameter is used to satisfy the the enter keybind
global array
# array = []
sname=serventry.get()
lname=lnentry.get()
pname=passentry.get()
array = [sname, lname, pname]
logwin.destroy()
print("userinfoalt() = ", array)
return array
# Create GUI
servlabel = Label(logwin, text="Server Address: ")
servlabel.grid(row=0, column=0)
serventry = Entry(logwin)
serventry.grid(row=0, column=1)
serventry.focus()
lnlable = Label(logwin, text="User Name: ")
lnlable.grid(row=1, column=0, padx=5)
lnentry = Entry(logwin)
lnentry.grid(row=1, column=1, padx=4)
passlabel = Label(logwin, text="Enter Password: ")
passlabel.grid(row=2, column=0)
passentry = Entry(logwin, show="*")
passentry.grid(row=2, column=1)
bsubmit = Button(logwin, text="Submit", command=userinfo, default='active')
bsubmit.grid(row=4, column=1, columnspan=2)
logwin.bind('<Return>', userinfoalt) # binds alternate credentials function to the return key.
logwin.mainloop()
print("login() end:", array)
return(array)
Logging in...")
credentials = login()
return(credentials)
def login():
# Create logwin window
logwin = Toplevel()
logwin.title("Log In")
# Called by login() GUI/bsubmit - returns credentials from log in GUI
def userinfo():
global array
# array = []
sname=serventry.get()
lname=lnentry.get()
pname=passentry.get()
array = [sname, lname, pname]
logwin.destroy()
print("userinfo() = ", array)
return array
# Called by login() GUI/ enter key from log in GUI
def userinfoalt(event): # event parameter is used to satisfy the the enter keybind
global array
# array = []
sname=serventry.get()
lname=lnentry.get()
pname=passentry.get()
array = [sname, lname, pname]
logwin.destroy()
print("userinfoalt() = ", array)
return array
# Create GUI
servlabel = Label(logwin, text="Server Address: ")
servlabel.grid(row=0, column=0)
serventry = Entry(logwin)
serventry.grid(row=0, column=1)
serventry.focus()
lnlable = Label(logwin, text="User Name: ")
lnlable.grid(row=1, column=0, padx=5)
lnentry = Entry(logwin)
lnentry.grid(row=1, column=1, padx=4)
passlabel = Label(logwin, text="Enter Password: ")
passlabel.grid(row=2, column=0)
passentry = Entry(logwin, show="*")
passentry.grid(row=2, column=1)
bsubmit = Button(logwin, text="Submit", command=userinfo, default='active')
bsubmit.grid(row=4, column=1, columnspan=2)
logwin.bind('<Return>', userinfoalt) # binds alternate credentials function to the return key.
logwin.mainloop()
print("login() end:", array)
return(array)
In the below code two tkinter entry is created entry1 and entry2 respectively for username and password. What I am looking for is storing the value entered in the tkinter entry to the database table admin_details. But nothing is passed. Also I have no idea in using the condition i.e. " retrieve the values inserted in the tkinter entry and store the data inside the table after the button Login is pressed."
Code is something like below:
import MySQLdb as mdb
from Tkinter import *
from tkMessageBox import *
root = Tk()
test=StringVar()
label1=Label(root,text='Username').grid()
entry1 = Entry(root, textvariable='uname')
entry1.grid()
label2=Label(root,text='password').grid()
entry2 = Entry(root, textvariable='pword')
entry2.grid()
print entry2
uname = entry1.get()
pword= entry2.get()
tup=[uname,pword]
option1 = Button(root, text = 'Login', command = next)
option1.grid()
if uname!='':
def next():
con = mdb.connect('localhost', 'root', 'root', 'kuis');
with con:
cur = con.cursor()
insert_sql = 'INSERT INTO admin_details(username, password) VALUES("{0}","{1}")'.format(*tup)
cur.execute(insert_sql)
root.mainloop()
The obvious problem is you are getting the text from both Entries directly after they have been initialized. The two variables you are using for this will not be changed when the Text in the Entries changes.
Here is some basic code how to retrieve the values from the two entry fields and pass them to a function:
import tkinter as Tk
import tkinter.messagebox
def show_pass_user(password, user):
# show what we got
tkinter.messagebox.showinfo("Data received", "Hey just got your username \"" + user + "\"" +
" and password \"" + password + "\"")
# run your sql here
def main():
root = Tk.Tk()
entry_user = Tk.Entry(root)
entry_user.insert(0, "Username")
entry_pass = Tk.Entry(root)
entry_pass.insert(0, "Password")
# use a lambda to get Username and Password when button is pressed
pressme = Tk.Button(root, text="Press Me", command=lambda:
show_pass_user(entry_pass.get(), entry_user.get()))
entry_user.grid()
entry_pass.grid()
pressme.grid()
root.mainloop()
if __name__ == "__main__":
main()
This code runs only with Python3!
Hi so basically I want my program to 'log in' whenever i hit the enter key. How would I do this?
My code:
def Login(event=None):
Db() #calls the database function/ subroutine
if USERNAME.get() == "" or PASSWORD.get() == "":
lbl_text.config(text="Please fill in the required details", fg="red", font="Arial")
PASSWORD.set("") #resets the password field to nill (with no username the password field is useless)
else:
cursor.execute("SELECT * FROM `member` WHERE `username` = ? AND `password` = ?", (USERNAME.get(), PASSWORD.get())) #username and password retrieved from database
if cursor.fetchone() is not None:
Home()
PASSWORD.set("") #resets password field to nill, so nobody can log in with same credentials if the log in window is left open
lbl_text.config(text="")
else:
lbl_text.config(text="Incorrect Details entered", fg="red", font="Arial")
PASSWORD.set("") #resets the password field to nill (I don't do the same with the password field, as the password field is typically wrong)
cursor.close()
conn.close()
btn_login = Button(Form, text="Login", width=45, command=Login)
btn_login.grid(pady=25, row=3, columnspan=3)
btn_login.bind('<Return>', Login)
Thanks
You can bind enter to a function in tkinter:
from tkinter import *
window = Tk()
window.geometry("600x400")
window.title("Test")
def test(event):
print("Hi")
window.bind("<Return>", test)
window.mainloop()