2

The Incorrect-Dimiss button erases on click and when Return key is pressed, but if I enter anything afterwards, nothing happens. The issue is that if I enter it correct, the login button pops up and it works. If I enter it incorrect, the dismiss button pops up, and clicking or pressing enter erases it. Now, anything I enter after an incorrect attempt whether correct or incorrect does nothing.

(1) In order to avoid this, I was wondering if the program could just restart on clicking/pressing enter the dismiss button, without the window closing, or another reopening, but I do not know how to do this.

(2)Also is there a max login attempts code that ends/restarts the program and if so how would I place it in this code? (something like if >3 incorrect then quit)

Here is the code (python3)- try it for yourself if you would like:

from tkinter import *

class Application(object):
    def __init__(self, event=None):
        self.root = Tk()

        self.root.configure(bg="darkorchid1", padx=10, pady=10)
        self.root.title("WELCOME")

        self.username = "Bob"

        self.welcome = Label(self.root, text="WELCOME TO MY PROGRAM", bg="lightgrey", fg="darkorchid1")
        self.welcome.pack()

        self.label0 = Label(self.root, text="ENTER NAME:", bg="purple", fg="white", height=5, width=50)
        self.label0.pack()

        self.entry = Entry(self.root, width=25)
        self.entry.configure(fg= "white",bg="grey20")
        self.entry.pack()
        self.entry.bind("<Return>", self.submit)

        self.button = Button(self.root, text="SUBMIT", highlightbackground="green", width=48, command=self.submit)
        self.button.pack()

    def submit(self, event=None):
        username = self.entry.get()
        if username == self.username:
            self.button1 = Button(self.root, text='LOGIN', highlightbackground="green", width=28, command=self.root.destroy)
            self.button1.pack()
            self.entry.bind("<Return>", self.login)

        else:
            self.button2 = Button(self.root, text="INCORRECT- CLICK TO DIMISS THIS MESSAGE", highlightbackground="red", width=48, command=self.incorrect)
            self.button2.pack()
            self.entry.bind("<Return>", self.incorrect)

    def incorrect(self, event=None):
        self.button2.destroy()

    def login(self, event=None):
        self.root.destroy()


app=Application()

mainloop()

Instead of destroying the button I want this to restart the program but cannot find the correct command. This would destroy the button since it doesn't exist at the beginning of the program, as well as allow for incorrect or correct input to actually work after the first try.

    def incorrect(self, event=None):
        self.button2.destroy()

I am a beginner so the more simple, the better at this point. Thank you.

2 Answers 2

3

Not an expert myself but fiddled with TKinter some time ago. From what I know the only way to restart a TKinter app is by running it in a thread and then killing and restarting that thread. I would recommend you to take a look at Python's multiprocessing or threading module.

Something you could also try (which worked for me in that past, but isn't really the correct way of doing this I suppose) is to have ROOT = Tk()as a global variable, then having your submit-button as a stand-alone class and have it import global ROOT before executing ROOT.Destroy() and then have it call the application class again, which can also call the global variable (which would cause it to start again). It's a method I've used to have the TKinter window update while I was using it. But the threading method is often mentioned as the proper way of doing this as far as I know..

As a very limited example (short on time for a more extensive one), I did something like this in my old script:

ROOT_WINDOW = ""
VARIABLE1 = 'some variable here'

def func1():

    global ROOT_WINDOW
    global VARIABLE1
    ROOT_WINDOW = Tk()
    #(Insert application code that uses or requires variable1)
    func2()

def func2():
    global ROOT_WINDOW
    global VARIABLE1
    ROOT_WINDOW.Destroy()
    Change variable1
    func1() 

With regard to setting a maximum number of login attempts. I solved this by creating a separate startup script. It works correctly but I dare not to post it here as it is a real ugly and incorrect way of solving the problem that also comes with a security issue (of having to store your sudo password within a variable).

Sorry for not being able to be of more help.

Sign up to request clarification or add additional context in comments.

Comments

1

First of all I would change the bind to return to the root window instead of the entry (otherwise you have to click on the entry field for the return to have an effect)

Next you need 3 state variables for your class.

self.button1 = None
self.button2 = None
self.attempts = 0

Then by checking the state of each you can accomplish (what I think) you want

Here’s the whole code modified

from tkinter import *

class Application(object):

    def __init__(self, event=None):

        self.root = Tk()

        self.root.configure(bg="darkorchid1", padx=10, pady=10)
        self.root.title("WELCOME")

        self.username = "Bob"

        self.welcome = Label(self.root, text="WELCOME TO MY PROGRAM", bg="lightgrey", fg="darkorchid1")
        self.welcome.pack()

        self.label0 = Label(self.root, text="ENTER NAME:", bg="purple", fg="white", height=5, width=50)
        self.label0.pack()

        self.entry = Entry(self.root, width=25)
        self.entry.configure(fg= "white",bg="grey20")
        self.entry.pack()
        self.root.bind("<Return>", self.submit)

        self.button = Button(self.root, text="SUBMIT", highlightbackground="green", width=48, command=self.submit)
        self.button.pack()

        self.button1 = None
        self.button2 = None
        self.attempts = 0

    def submit(self, event=None):
        username = self.entry.get()
        if username == self.username:
            if (self.button2 != None): # after I added disabling the submit button this check might not be necessary
                return
            if (self.button1 == None):
                self.button1 = Button(self.root, text='LOGIN', highlightbackground="green", width=28, command=self.root.destroy)
                self.button1.pack()
                self.root.bind("<Return>", self.login)
                self.button.config(state="disabled")
        else:
            if (self.button2 == None):
                self.button2 = Button(self.root, text="INCORRECT- CLICK TO DIMISS THIS MESSAGE", highlightbackground="red", width=48, command=self.incorrect)
                self.button2.pack()
                self.root.bind("<Return>", self.incorrect)
                self.button.config(state="disabled")

    def incorrect(self, event=None):
        self.attempts += 1
        if (self.attempts > 2):
            self.root.destroy()
        else:
            self.root.bind("<Return>", self.submit)
            self.button.config(state="normal")
            self.button2.destroy()
            self.button2 = None

    def login(self, event=None):
        self.root.destroy()

app=Application()

mainloop()

11 Comments

You could also move the attempts check to where you create button2 (so then there would be no need to press the incorrect button on the last try)
Wow thank you so much @jross for your time and help. A few quick questions: why += 1 instead of + 1? why set the variables to None? Also i thought return only worked for "while" and "for" statements. it works for def too? Where exactly does it return to?
@gmonz +=1 is the same thing as saying (self.attempts = self.attempts + 1) it's just a shortcut
@gmonz I set self.button2 to None after destroying it, because the variable self.button2 would still contain a reference to the destroyed object if we didn't. None means, this variable does not point to anything.
Now my rep is 20 so I was able to upvote you as well! :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.