Theo Pearson-Bray
Theo Pearson-Bray

Reputation: 775

Python- How to make a function wait or use a while loop in tkinter without the window freezing

I have set up a GUI for a simple encryption program using Tkinter, it uses Entry() boxes for the key and input. What I am attempting is to force the use to re-enter a key if they leave the key box blank and hit encrypt. Previously the program would just generate a random key for them and show it using messagebox.showinfo as well as putting it in the key box with Key_Box.insert(0, Key)

What I am using now is redirection, Key_Box.focus(), and a messagebox.showinfo telling the user that they haven't entered a key. The problem is that I can't stop the function from continuing after this point, it just runs on. When the whole program was text based I could just put

while Key == "":
    Key = input("Input a new key:")

But with Tkinter using a while loop or time.sleep(n) stops the program from responding (understandably as it all runs in a loop).

So, how can I get the program to do this-

psuedo- if Key == "":
            cursor at Key_Box 
            display ok button
            until OK is pressed:
                repeat
            else:
                key = Keybox.get()

The rest of my code looks like this- Note- It needs a cleanup, or does Tkinter always look a bit messy

import time, random
from tkinter import *
root = Tk()

##Encrypt and Decrypt
Master_Key = "0123456789 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#£$%&'()*+,-./:;?@[\\]^_`{|}~r\x0b\x0c"
def Encrypt(User_Input, Key):
    Output = ""
    for i in range(len(User_Input)): 
        Ref_For_Output = Master_Key.index(User_Input[i]) + Master_Key.index(Key[i])
        if Ref_For_Output >= len(Master_Key):        
            Ref_For_Output -= len(Master_Key)
        Output += Master_Key[Ref_For_Output]
    return Output 
def Decrypt(User_Input, Key):
    Output = ""
    for i in range(len(User_Input)):
        Ref_For_Output = Master_Key.index(User_Input[i]) - Master_Key.index(Key[i])
        if Ref_For_Output < 0:
            Ref_For_Output += len(Master_Key)
        Output += Master_Key[Ref_For_Output]
    return Output    

def Compatibility(User_Input, Key):
    if Key == "":
##        while len(Key) < 5:
##            Key += Master_Key[random.randint(0, (len(Master_Key)-1))]
##        Key_Box.insert(0, Key)
##        messagebox.showinfo(title="Error!", message="Your key cannot be blank, your new randomly generated key is: \n" + Key)
        Key_Box.focus()
    Temp = 0
    while len(Key) < len(User_Input): 
        Key += (Key[Temp])
        Temp += 1
    return Key

##Layout
root.title("A451 CAM2")
#root.geometry("300x100")- Window will resize as I add to the Output_Box
##Input label
Label1 = Label(root, text="Input: ")
Label1.grid(row=0, column=0, padx=10)
##Key label
Label2 = Label(root, text="Key:   ")
Label2.grid(row=1, column=0, padx=10)
##Output label
Label3 = Label(root, text="Output: ")
Label3.grid(row=2, column=0, padx=10)
##Input entry box
Input_Box = Entry(root, bg="grey60")
Input_Box.grid(row=0, column=1)
#Key entry box
Key_Box = Entry(root, bg="grey60")
Key_Box.grid(row=1, column=1)
##The Output box
Output_Box = Text(root, height=1, width=15)
Output_Box.grid(row=2, column=1, rowspan=2)

##Encrypt button action- Manages setting input, checking the key, changing the Encrypt button, showing a message, changing output box, and adding to clipboard
def Encrypt_Button_Press():
    User_Input = Input_Box.get()
    Key = Compatibility(User_Input, Key_Box.get())
    root.clipboard_append(Encrypt(User_Input, Key))
    Encrypt_Button.configure(text="Encrypting")
    Encrypt_Button.configure(text="Encrypt")
    Output_Box.insert(INSERT, Encrypt(User_Input, Key) + "\n")
    New_Height = Output_Box.cget("height") + 1
    Output_Box.configure(bg="green4", height=New_Height)
    messagebox.showinfo("Complete", "Your encrypted text is: \n" + Encrypt(User_Input, Key) + "\n The text has been added to your clipboard.")
##Decrypt button action- Manages setting input, checking the key, changing the Decrypt button, showing a message, changing output box, and adding to clipboard 
def Decrypt_Button_Press():
    User_Input = Input_Box.get()
    Key = Key = Compatibility(User_Input, Key_Box.get())
    root.clipboard_append(Decrypt(User_Input, Key))
    Decrypt_Button.configure(text="Decrypting")
    Decrypt_Button.configure(text="Decrypt")
    Output_Box.insert(INSERT, Encrypt(User_Input, Key) + "\n")
    New_Height = Output_Box.cget("height") + 1
    Output_Box.configure(bg="green4", height=New_Height)
    messagebox.showinfo("Complete", "Your Decrypted text is: \n" + Decrypt(User_Input, Key) + "\n The text has been added to your clipboard.")
##The Clear button action
def Clear_All():
    Input_Box.delete(0,END)
    Key_Box.delete(0, END)
    Output_Box.delete(1.0, END)
    Output_Box.configure(bg="grey60", height=1)

##The Encrypt button
Encrypt_Button = Button(text="Encrypt", command=Encrypt_Button_Press, width=10, bg="green")
Encrypt_Button.grid(row=0, column=3, padx=10)
##The Decrypt button
Decrypt_Button = Button(text="Decrypt", command=Decrypt_Button_Press, width=10, bg="orange")
Decrypt_Button.grid(row=1, column = 3, padx=10)
##The clear button
Clear_Button = Button(text="Clear", command=Clear_All, bg="red", width=10)
Clear_Button.grid(row=2, column=3)


root.mainloop() 

Thank you in advance for your help, I looked up after() but that involves calling more functions and doesn't seem to apply very well to what I am trying to do.

Upvotes: 0

Views: 1023

Answers (1)

MeetTitan
MeetTitan

Reputation: 3568

You could put the blocking code in it's own thread, allowing it to loop or block as written.

Upvotes: 1

Related Questions