0

This is the code for my personal project, for some reason, I can't get the button to do anything when pressed.

Edit: So I managed to fix the text deleting after each input, so now it will continue to output as many passwords as I want. I removed the 0.0 in output.delete so it doesn't default the text to 0 after each generated password.

from tkinter import *
from datetime import datetime
import pyperclip as pc





def close_window():
    window.destroy()
    exit()


# Main GUI program

window = Tk()
window.frame()
window.grid_rowconfigure((0, 1), weight=1)
window.grid_columnconfigure((0, 1), weight=1)
window.title("PW Gen")
window.geometry('+10+10')
window.configure(background="black")
Label(window, bg="black", height=0, width=25, font="Raleway").grid(row=1, column=0, sticky=NSEW)

# Enter the last 4 and generate the password
Label(window, text="Enter the last 4 digits of the Reader Name:", bg="black", fg="white", font="Raleway 12 bold").grid(row=1, column=0, sticky=W)
textentry = Entry(window, width=53, bg="white")
textentry.grid(row=2, column=0, sticky=W)
Button(window, text="Generate Password", width=16, font="Raleway 8 bold", command=click).grid(row=3, column=0, sticky=W)

# Output the password
Label(window, text="\nPassword", bg="black", fg="white", font="Raleway 12 bold").grid(row=4, column=0, sticky=W)
output = Text(window, width=40, height=4, wrap=WORD, background="white")
output.grid(row=5, column=0, columnspan=2, sticky=W)

# Button and Text To Quit GUI
Label(window, text="Click to Quit", bg="black", fg="white", font="Raleway 12 bold").grid(row=6, column=0, sticky=W)
Button(window, text="Quit", width=14, font="Raleway 8 bold", command=close_window).grid(row=7, column=0, sticky=W)

window.mainloop()


Mocha
  • 1
  • 2
  • Why would it? ```tk.Button(TOP, text="Generate PW", command=pwgen)```. You gave ```Tk``` instead of ```tk``` –  Jul 03 '21 at 17:31
  • First of all why do you have `app.mainloop()` and then `root.mainloop()`? There is no point and it might even raise an error. Also you are using `self.b1` for a method, a button (defined in `__init__`), and another button (defined in `b1`)??? Why? – TheLizzard Jul 03 '21 at 17:31
  • `self.b1["command"] = self.b1` is calling itself?! – Derek Jul 03 '21 at 17:33
  • 1
    This code doesn't make sense? You are renaming functions as Button, setting command as the button –  Jul 03 '21 at 17:35
  • And why are you using a ```while``` loop? –  Jul 03 '21 at 17:36
  • When `pwgen()` enters the infinite loop, the tkinter GUI will freeze. – martineau Jul 03 '21 at 17:37
  • @Sujay The while loop is for the program to continue to run after getting input so you could essentially get multiple passwords generated. The while script alone works fine, I'm just trying to integrate it into a GUI. – Mocha Jul 03 '21 at 17:39
  • Then use a ```for``` loop? A ```while``` loop continues until a condition is ```True```, and the condition in your code is never ```False```, so, infinite passwords are generated –  Jul 03 '21 at 17:41
  • @Mocha Please look at some basic `tkinter`/`python` tutorials. It seems that you have quite a few misconceptions/bugs in your code – TheLizzard Jul 03 '21 at 17:41
  • @Sujay Also notice the `input` inside the loop. Even if OP removes the `while True` loop, `tkinter` will still become unresponsive. – TheLizzard Jul 03 '21 at 17:42
  • @TheLizzard lol will do, I'm just messing with Python for fun trying to learn. You guys gave me a lot of good advice so I'll work on it haha – Mocha Jul 03 '21 at 17:42
  • @Mocha Look at your first label: `Label(...).grid(row=0, column=0, ...)`, it's taking up space without doing anything. – TheLizzard Jul 04 '21 at 20:10
  • @Mocha Also look this: `int(today.strftime("%d")) * int(today.strftime("%m"))`. It takes the day and multiplies it by the month. So if you want a new password you will have to wait at least one day. Or change that line of code (the easier option). – TheLizzard Jul 04 '21 at 20:14
  • @TheLizzard I just fixed the gap at the top, as for the new password what would you recommend instead? – Mocha Jul 04 '21 at 20:20
  • @Mocha Try adding `from hashlib import sha256` at the start of your code then use `sha256(f"{datetime.today().strftime('%f')}{textentry.get()}".encode()).hexdigest()[:15]` instead of the `"$ynEL" + str(pw) + textentry.get()`. If you want, I can tell you how it works but it's quite a long explanation – TheLizzard Jul 04 '21 at 20:31
  • @TheLizzard Oh no worries you already helped me out a ton haha, hopefully, the new code is better. Idk if you tried to run it yet but it should be updated and work as needed atm. Just gotta do some things to make it better. – Mocha Jul 04 '21 at 20:37

3 Answers3

0

Not exactly the best solution but you can definitely give it a try.

import tkinter as tk
from datetime import datetime
import string
import pyperclip as pc
import random
root = tk.Tk()
root.title("PW Gen")
root.geometry('+10+10')
mainframe = tk.Frame(root)
text = tk.Text(root, height=5, width=25, font="Raleway")
def pwgen():
    last4=text.get('1.0','end')[-5:]
    j=[char for char in last4 if char in string.ascii_uppercase or  char in string.ascii_lowercase]
    print(j)
    random.shuffle(j)
    print(j)
    today = datetime.today()
    pw = int(today.strftime("%d")) * int(today.strftime("%m"))
    last4=''.join(j)
    pwgen = "$ynEL" + str(pw) + str()
    pc.copy(pwgen)
    print("\nThe password is $ynEL" + str(pw) + str(last4))
class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.quit1 = tk.Button(self, text="QUIT", fg="black", command=self.master.destroy)
        self.quit1.pack(side="top")
        text.pack(side="bottom")
        self.b2 = tk.Button(self)
        self.create_widgets()
        self.pack()
    def create_widgets(self):
        self.b2["text"] = "GenPW"
        self.b2["command"] = pwgen
        self.b2.pack(side="left")
    def b1(self):
        self.b2 = tk.Button(self, text="Generate PW", command=pwgen)
app = Application(root)
root.mainloop()
  • thank you for the constructive criticism, I appreciate your help. Also thank you for your solution, I was probably trying to way overcomplicate things as I'm new to Python and just trying to learn. – Mocha Jul 03 '21 at 17:56
  • @Sujay You know that nothing is using `mainframe`. The `Text` widget named `text` is useless. And you aren't even using the `b1` method. – TheLizzard Jul 03 '21 at 17:56
0

The code has many problems. mainframe is not shown and never used. Text is shown, but never used. Text is packed inside Application but is not part of Application.

pwgen uses input and no GUI widget. A infinte loop with a GUI application is not good. You should use the attributes of a datetime directly. You should not generate the password at two places in the code. You should not name a local variable like the function. In Application you are using b1 as method, this method is overloaded by the attribute b1, so you cannot use the method anymore. In the method b1 you are generating a new butten instead of calling the function pwgen.

import tkinter as tk
from datetime import datetime
import pyperclip as pc

def pwgen():
    today = datetime.today()
    pw = today.day * today.month
    last4 = input("Last 4 of Reader Name [****] ")
    password = f"$ynEL{pw}{last4}"
    pc.copy(password)
    print("\nThe password is", password)


class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.quit = tk.Button(self, text="QUIT", fg="black", command=self.master.destroy)
        self.quit.pack(side="top")
        self.b1 = tk.Button(self, text="GenPW", command=self.click_b1)
        self.b1.pack(side="left")

    def click_b1(self):
        pwgen()


def main():
    root = tk.Tk()
    root.title("PW Gen")
    root.geometry('+10+10')
    text = tk.Text(root, height=5, width=25, font="Raleway")
    text.pack(side="bottom")
    app = Application(master=root)
    app.pack()
    root.mainloop()

if __name__ == "__main__":
    main()
Daniel
  • 42,087
  • 4
  • 55
  • 81
  • The `input(...)` that's inside the `pwgen` function will make `tkinter` unresponsive. Isn't it better to use the `Text` widget that's defined inside `main`? Make it a global variable? – TheLizzard Jul 03 '21 at 18:13
  • @TheLizzard I updated the code in the post above, let me know what you think now. I got rid of the useless stuff and I did what you said and used the attributes directly to generate the password. I just cant figure out why there is a massive gap when running the program, and how to allow the program to generate multiple passwords without deleting the previous ones. – Mocha Jul 04 '21 at 20:01
  • @Mocha Your first label doesn't have any text but takes up a height of 5 characters. That is why you have gap there. Also look this: `int(today.strftime("%d")) * int(today.strftime("%m"))`. It takes the day and multiplies it by the month. So if you want a new password you will have to wait at least one day. Or change that line of code (the easier option). – TheLizzard Jul 04 '21 at 20:14
0

This works. I have used grid manager for more control and removed unused code.


import tkinter as tk
from tkinter import *
from datetime import datetime
import pyperclip as pc

root = tk.Tk()
root.title("PW Gen")
root.geometry('+10+10')
Text = tk.Text(root, height=5, width=25, font="Raleway")

def pwgen():
    while True:
        today = datetime.today()
        pw = int(today.strftime("%d")) * int(today.strftime("%m"))
        last4 = input("Last 4 of Reader Name [****] ")
        pwgen = "$ynEL" + str(pw) + str(last4)

        pc.copy(pwgen)
        print("\nThe password is $ynEL" + str(pw) + str(last4))


class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.quit = tk.Button(self, text="QUIT", fg="black", command=self.master.destroy)
        self.quit.grid(row=0,column=0,sticky=tk.EW)
        Text.grid(row=1,column=0,sticky=tk.NSEW)
        self.b1 = tk.Button(self, text="Generate PW", command=pwgen)
        self.b1.grid(row=0,column=1,sticky=tk.EW)
        self.grid(row=0,column=0,sticky=tk.NSEW)

app = Application(master=root)
root.mainloop()

A previous version created multiple Generate PW buttons.

Derek
  • 1,916
  • 2
  • 5
  • 15
  • The `tkinter` window will stop responding when it enters the `while True` loop. Also you don't seem to be using the `Text` widget for anything. – TheLizzard Jul 03 '21 at 19:06
  • @TheLizzard I had to rem out `import pyperclip as pc` since it's not a standard python module. The problem of a non responsive button is solved. I assume @Sujay will continue to develop `pwgen` now that road block is clear. – Derek Jul 04 '21 at 01:44