-1

I am trying to create a password manager in python with tkinter. But when I try to write the account name, username and password it doesn't work. I am using a text box with StringVar to get the info from the textboxes. I don't know if the bug is in the textboxes or the writing to the file. I have the following code:

from tkinter import *
from tkinter import messagebox

loginwin = Tk()
loginwin.wm_title("Login")
loginwin.geometry("225x75")

win = Tk()
win.wm_title("Password Manger")
win.geometry("550x215")
win.withdraw()

u = StringVar()
p = StringVar()

a = StringVar()
u1 = StringVar()
p1 = StringVar()

def login():
    username1 = u.get()
    password1 = p.get()
    if username1 == "":
        if password1 == "":
            messagebox.showinfo("Login", "Login Complete")
            loginwin.withdraw()
            win.deiconify()
        else:
            messagebox.showinfo("Login", "Incorrect Password or Username")
    else:
        messagebox.showinfo("Login", "Incorrect Password or Username")

def add():
        account1 = a.get()
        username2 = u1.get()
        password2 = p1.get()
        account1 = str(account1)
        username2 = str(username2)
        password2 = str(password2)
        with open("passwords.txt", "w") as file:
                file.write("\n" + account1 + " " + username2 + " " + password2)

Label(loginwin, text="   Username:  ").grid(row=1, column=1)
Label(loginwin, text="   Password:  ").grid(row=2, column=1)
Label(loginwin, text="Hint: Nothing").grid(row=3, column=2)

Label(win, text="   Account:  ").grid(row=1, column=1)
Label(win, text="   Username: ").grid(row=2, column=1)
Label(win, text="   Password: ").grid(row=3, column=1)

username = Entry(loginwin, textvariable = u)
username.grid(row=1, column=2)
password = Entry(loginwin, textvariable = p, show = "*")
password.grid(row=2, column=2)

account = Entry(win, textvariable = a)
account.grid(row=1, column=2)
username1 = Entry(win, textvariable = u1)
username1.grid(row=2, column=2)
password1 = Entry(win, textvariable = p1)
password1.grid(row=3, column=2)

login = Button(loginwin, text="Login", command=login)
login.grid(row=3, column=1)

add = Button(win, text="Add", command=add)
add.grid(row=4, column=1)

loginwin.mainloop()
win.mainloop()
  • 1
    Please do not include pleas in the title or body. – jhpratt Aug 19 '18 at 00:31
  • Sorry, can you help me –  Aug 19 '18 at 00:36
  • Aside from the pleas you haven't removed, "it doesn't work" is not a valid problem. What doesn't work? Have you run your program through a debugger to narrow down the lines? – jhpratt Aug 19 '18 at 00:38
  • I will try that, Thanks –  Aug 19 '18 at 00:40
  • I haven't done any tkinter programming, so maybe this is the way you're supposed to do it, but the line `add = Button(win, text="Add", command=add)` seems odd to me -- you're creating a new object named `add` which destroys the existing `add()` function. – John Gordon Aug 19 '18 at 00:40
  • It come up with no errors –  Aug 19 '18 at 00:41
  • I will try that –  Aug 19 '18 at 00:41
  • @JohnGordon Actually, he's just passing the current value of `add`, which is looked up before rebinding the name, so it should work… but it's still at best very confusing, so you're right, he should change that. – abarnert Aug 19 '18 at 00:41
  • It dosesn't work –  Aug 19 '18 at 00:43
  • The function name `add()` is misleading at best -- the file is opened in `w` mode which destroys the previous contents, so you're not really "adding" to the current file. Although if as you say it isn't writing to the file at all, perhaps this is a red herring. – John Gordon Aug 19 '18 at 00:44
  • I changed the name of the button, but it doesn't work –  Aug 19 '18 at 00:48
  • How do I fix the StringVar –  Aug 19 '18 at 00:49
  • @JohnGordon Yeah, that's also something that should be fixed (probably by appending to the file rather than overwriting it, rather than by renaming the button and commands…). – abarnert Aug 19 '18 at 01:11

2 Answers2

1

Your problem is that you have to separate Tk root objects.

The short version is that the simplest, and almost certainly best, way to fix this is to not do that. Change this line:

win = Tk()

… to this:

win = Toplevel(loginwin)

And get rid of this line:

win.mainloop()

You probably also have a second problem: by opening the file in w mode instead of a mode, you're erasing whatever was there, but I doubt that's what you wanted. So, do this:

with open("passwords.txt", "a") as file:

If you want to understand what's wrong: The short version is that you should never, ever have two Tk root objects in the same program unless you really know what you're doing and have a very good reason. The long version is a bit more complicated, but I'll try.


The first problem is that each root has its own separate Tcl environment, meaning it has its own separate global variables holding the contents of those StringVars, and so on.

When you do this:

u = StringVar()

… that creates a Tcl variable named something like Py_VAR0 in the default root, the first one you created, loginwin, and attaches the Python variable u to that Tcl variable.

When you do this:

account = Entry(win, textvariable = a)

… that tells the Entry to store its text in something named Py_VAR0 in its root. But its root is win, not loginwin. So, every time the text changes, the contents of Py_VAR0 inside the win root change, but the contents of Py_VAR0 inside the loginwin root do not.

When you do this:

account1 = a.get()

… since a is the Py_VAR0 of loginwin, not the Py_VAR0 of win, you don't get the changed value, you get the default value for a StringVar, which is an empty string.

And the same goes for your other variables.

So, when you do this:

    with open("passwords.txt", "w") as file:
            file.write("\n" + account1 + " " + username2 + " " + password2)

… you're opening passwords.txt and erasing it (that's what w mode means), then writing this:

"\n" + "" + " " + "" + " " + ""

… which isn't actually nothing, but it might well look like nothing in your text editor, because it's just a 2-line file with nothing on the first line and two spaces on the second.

You could fix this problem by explicitly giving each StringVar the right root as a parent, just like any other Tkinter object:

u = StringVar(win)

The second problem is that each root needs it own mainloop.

Just running one after the other means the second one doesn't get to run until the first one has exited. Which means any code attached to any widgets on win isn't going to run at all until loginwin exits.

That means that your Entry(win, textvariable = a) isn't active and receiving events, so it's not even going to set the wrong string variable; it's just not going to do anything at all.

The only way to fix this is to manually interweave the two loops together—to have one drive the other one. This isn't that hard, but it's not exactly trivial, either.


But the easier fix to both problems is to just not have two roots.

If you really do need two separate roots for some reason, then you have to manage their variables and mainloops properly.

But if you were doing this because you wanted another top-level window, use Toplevel for that.

And if you were doing this for some other reason… well, it depends why you were doing it, but having two roots probably isn't the right answer.

abarnert
  • 354,177
  • 51
  • 601
  • 671
0

Your code has several problems.

You are using <var>.get() to get the text in the entry but if you try printing its output then you will get the entry name, not the text. Use <entry>.get() to get the text.


You are using open("<file>","w") whereas the mode w is used to rewrite the file. I will suggest you to use mode a which appends data automatically at the end of file.


You are not closing your file after writing data.


add is the name of function but you are making a button naming add. Similar with login. Give these buttons a different name.


Your updated code is:

from tkinter import *
from tkinter import messagebox

loginwin = Tk()
loginwin.wm_title("Login")
loginwin.geometry("225x75")

win = Tk()
win.wm_title("Password Manger")
win.geometry("550x215")
win.withdraw()

u = StringVar()
p = StringVar()

a = StringVar()
u1 = StringVar()
p1 = StringVar()

def login():
    username1 = u.get()
    password1 = p.get()
    print(username1,password1)
    if username1 == "":
        if password1 == "":
            messagebox.showinfo("Login", "Login Complete")
            loginwin.withdraw()
            win.deiconify()
        else:
            messagebox.showinfo("Login", "Incorrect Password or Username")
    else:
        messagebox.showinfo("Login", "Incorrect Password or Username")

def add():
        account11 = str(account.get())
        username22 = str(username1.get())
        password22 = str(password1.get())
        file = open("passwords.txt", "a")
        file.write("\n" + account11 + " " + username22 + " " + password22)
        file.close()

Label(loginwin, text="   Username:  ").grid(row=1, column=1)
Label(loginwin, text="   Password:  ").grid(row=2, column=1)
Label(loginwin, text="Hint: Nothing").grid(row=3, column=2)

Label(win, text="   Account:  ").grid(row=1, column=1)
Label(win, text="   Username: ").grid(row=2, column=1)
Label(win, text="   Password: ").grid(row=3, column=1)

username = Entry(loginwin, textvariable = u)
username.grid(row=1, column=2)
password = Entry(loginwin, textvariable = p, show = "*")
password.grid(row=2, column=2)

account = Entry(win, textvariable = a)
account.grid(row=1, column=2)
username1 = Entry(win, textvariable = u1)
username1.grid(row=2, column=2)
password1 = Entry(win, textvariable = p1)
password1.grid(row=3, column=2)

button_login = Button(loginwin, text="Login", command=login)
button_login.grid(row=3, column=1)

button_add = Button(win, text="Add", command=add)
button_add.grid(row=4, column=1)

loginwin.mainloop()
win.mainloop()
Nouman
  • 6,947
  • 7
  • 32
  • 60