Python Forum
tkinter -- after() method and return from function -- (python 3)
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
tkinter -- after() method and return from function -- (python 3)
#1
Hello.I have 2 problems with my GUI. First of all I have 2 files ,one named GUI_password.py and the other one GUI_main.py.
Code of GUI_password.py below:

from tkinter import *
from tkinter import *
import tkinter.font as tkFont
from PIL import Image , ImageTk
from threading import Timer
import time
import threading
import asyncio



def delay(seconds):
      t0 = time.time()
      i = 1
      while (i <= 1):
         t1 = time.time()
         if(t1 - t0 > seconds):
            
            t0 = time.time()
            i+=1      



def Password(root , unlock_message , access_camera): # passcode => '12345'    

    activate_message = "SYSTEM ACTIVATED"
    denied_message = "ACCESS DENIED"
    wrong_attempts = 0  

    #root.configure(background = 'cyan')    # background color
    size_letter = tkFont.Font(family = "Helvetica" , size = 19 , weight = "bold")
    message_box = Label(root , text = "PLEASE ENTER ACCESS CODE" , font = size_letter).place(x = 558 , y = 30)
    
    user_input = StringVar() # user_+input holds a string (default value = "")
    input_box = Entry(root , show = "*" , width = 6 , font = ('Verdana' , 20) )
    input_box.place(x = 700 , y = 80)
    
    lock_logo = Image.open("lock_icon.jpg")
    lock_logo = lock_logo.resize( (50 , 50) , resample = 0)
    lock_image = ImageTk.PhotoImage(lock_logo)
    

    frame_for_lock_icon = LabelFrame(root , padx = 5 , pady = 5,relief = SUNKEN , bd = 0)
    label_for_lock = Label(frame_for_lock_icon , image = lock_image)
    label_for_lock.image = lock_image
    label_for_lock.grid(row = 0 , column = 0)
    frame_for_lock_icon.place(x = 725 , y = 200)
    my_var = False
  

    def check_passcode():
        nonlocal wrong_attempts , my_var     
        
        size_message_attempts = tkFont.Font(size = 13)
        
        if(input_box.get() == "12345"):
            print("RIGHT")
            frame_for_lock_icon = LabelFrame(root , padx = 5 , pady = 5,relief = SUNKEN , bd = 0)
            label_for_lock = Label(frame_for_lock_icon , image = lock_image)
            
            frame_for_lock_icon.configure(background = "green")
            frame_for_lock_icon.place(x = 725 , y = 200)
            label_for_lock.image = lock_image
            label_for_lock.grid(row = 0 , column = 0)
            entry_box = Entry(root , show = "*" , width = 6 , font = ('Verdana' , 20) , state = DISABLED).place(x = 700 , y = 80)
            button_ok = Button(root , text = "OK" , width = 7 , pady = 8 , command = check_passcode , state = DISABLED).place(x = 655 , y = 140)  
            button_cancel = Button(root , text = "CANCEL" , width = 7 , pady = 8 , command = root.quit , state = DISABLED).place(x = 770 , y = 140)
            #root.after(3000 , None)
            #frame_for_lock_icon.after_cancel(root)
            #entry_box.destroy()
            #button_ok.destroy()
            #button_cancel.destroy()
            my_var = True

        elif(input_box.get() != ""):
            blink_icon()
            Label(root , text = "(" + str(5 - wrong_attempts) + ")" , font = size_message_attempts).place(x = 585 , y = 145)
            wrong_attempts += 1
            print("WRONG")
            input_box.delete(0 , END)

        
        if(wrong_attempts == 6):
            print("6 wrong attempts were given")
            Entry(root , show = "*" , width = 6 , font = ('Verdana' , 20) , state = DISABLED).place(x = 700 , y = 80)
            Button(root , text = "OK" , width = 7 , pady = 8 , command = check_passcode , state = DISABLED).place(x = 655 , y = 140)  
            Button(root , text = "CANCEL" , width = 7 , pady = 8 , command = root.quit , state = DISABLED).place(x = 770 , y = 140)
            exit()
    
    if(my_var):
        return True
    ok_button = Button(root , text = "OK" , width = 7 , pady = 8 , command = check_passcode , borderwidth = 3).place(x = 655 , y = 140)  
    cancel_button = Button(root , text = "CANCEL" , width = 7 , pady = 8 , command = root.quit , borderwidth = 3).place(x = 770 , y = 140)  
    


    var = FALSE
    a = 1
    def blink_icon():
        #do stuff
        nonlocal var , a
        frame_for_lock_icon = LabelFrame(root , padx = 5 , pady = 5,relief = SUNKEN , bd = 0)
        label_for_lock = Label(frame_for_lock_icon , image = lock_image)
        
        t = Timer( 0.5 , blink_icon )
        t.start()
        #print("Var =   " + str(var))
        if(a == 5):
            t.cancel()
            a = 1
            return
        else:
            if(var == True):
                frame_for_lock_icon.place(x = 725 , y = 200)
                label_for_lock.image = lock_image
                label_for_lock.grid(row = 0 , column = 0)
            else:
                frame_for_lock_icon.configure(background = "red")
                frame_for_lock_icon.place(x = 725 , y = 200)
                label_for_lock.image = lock_image
                label_for_lock.grid(row = 0 , column = 0)
               
            var = not var
        a+=1
Code of GUI_main.py below:

from tkinter import *
from GUI_password import Password

root = Tk()
root.geometry("1800x1100")
root.title("Vehicle app")
access = Password(root , "unlock" , True)
if(access == True):
    print("DONE PASSWORD METHOD")

root.mainloop()
First of all, (if you run my code) ,you will understand what I want to say.
In GUI_password.py file ,in check_passcode() function ,when the passcode is correct,I want the frame_for_lock_icon to be green BUT FOR ONLY 2 SECONDS(for examle) and then I want to exit from check_passcode and from Password(...) method ,but I can't do that.
How can I fix it?

Any help will be appreciated.
Thanks.
Reply
#2
An example of using root.after(time, func) to reset an entry widget after 2 seconds.
import tkinter as tk

passwords = ('password')

def clear_password():
    """Set background to white and clear entry"""
    password['bg'] = 'white'
    password.delete(0, tk.END)

def check_password(event):
    """Verify password when entry/return is pressed"""
    if password.get() in passwords:
        password['bg'] = 'green'
    else:
        password['bg'] = 'red'
    root.after(2000, clear_password)
    
root = tk.Tk()

password = tk.Entry(root, width=20, show='*')
password.bind('<Return>', check_password)
password.pack(padx=10, pady=10)

tk.mainloop()
Reply
#3
What about return values and use them (for example) in my other file (GUI-main.py) as you can see my last post?
Reply
#4
If you provide a shorter example I will look at it
Reply
#5
A shorter example. I have a file named test_one.py which contains the following code:
from tkinter import *
root = Tk()
var = function(root)
if(var):
  print("hello world")

root.mainloop()
I also have a second file named test_two.py ,which contains:
from tkinter import *

def my_func(root):
   # do something here
   return True 


def function(root):
    my_button = Button(root , text = "Press" , command = lambda: my_func(root) ).pack()
So, I call function() (it is inside test_two.py) from test_one.py and function() has a button which when I press it I want to do something and finally I want to return a value(for example I want to return True) and after that I want to continue from test_one.py in order to print "hello world". I use tkinter and I don't know how to return values (without tkinter I can do that easily).
Am I clear? If not ,tell me to explain it again.
Thanks!!
Reply
#6
GUI programs are usually event driven. The user does something and you execute code to process what the user did. If you want a login screen you would have a button or a menu that pops up the login screen. It doesn't wait for a password. It doesn't care if you ever type anything into the dialog or close it. The code that pops open the login screen has done it's job, and that event handler is done.

The user types in their username and password. Maybe pressing the enter key is the accept event, or maybe the dialog has a button. Either way the user does something that indicates it is time to check the username and password. If the username and password are correct, the program executes some code associated with logging in (at the least closing the login window, probably putting the username in a status bar to show who is logged in). If the password or username is incorrect the program executes some code that is associated with a failed login (maybe drawing an error message, making a sound, probably closing the login window).

There is never any waiting in a GUI application. If you think you need to wait it usually means you are thinking about the problem the wrong way. Your program will spend most of it's time doing nothing. Doing nothing sounds like waiting, but there is one critical difference. An idle GUI program is always ready to respond to user events. A waiting program is unresponsive to user events.

To answer your question, "What about return values and use them (for example) in my other file (GUI-main.py) as you can see my last post?" There are no return values and GUI-main does now wait for Password() to complete. If the user enters the correct password, Password() will execute the login code that you probably, incorrectly, have in your GUI-main.py module.
Reply
#7
I did go back and look at the code in your original post. Do not post code that depends on images or other files that are not available to other forum users. I cannot run your code. I could rewrite your code to use different image files, or I could create some images for the code, but do you really want me to put that much effort into helping you when I have other matters demanding my time? The same goes for module dependencies. Only import modules that are absolutely necessary to demonstrate the problem you are trying to solve. I don't use many images, so I don't have PILLOW installed.

Don't fill you code with unnecessary gewgaw. There is no reason to set fonts or colors or have stylesheets unless you are having a problem setting a font, a color, or applying a stylesheet. You shouldn't be filling your programs with this crap anyway until you have the skeleton working. Spending time designing a pretty dialog is a waste of time if you eventually discover that a different approach eliminates the need for a dialog.
Reply
#8
Thank you for your information.
So,what you suggest me to do if password is correct in order to continue.(destroy all buttons/entry and continue?). Secondly, if I want to return value from a function, what should I do?
There will be some way.
I need a help here.
Thank you very much.
Your help will be appreciated!!
Reply
#9
I am not explaining things well. Your don't need to return values from your password function because there won't be any code waiting for those values.

Lets say you have a terminal program that looks like this:
def get_password()
    return input('Enter password: ') == '1234'

def main()
    if get_password():
        #code to do with successful password
    else:
        #code to do with failed password
To convert to a GUI program you need to change the layout completely.
class Password:
    def __init__(self, password, success, failure, args):
        self.password = password
        self.success = success
        self.failure = failure
        self.args = args
        entry_widget('enter password', callback=self.entered)

    def entered(self, text):
        if text == self.password:
            self.success(*self.args)
        else:
            self.failure(*self.args)
            
def successful_password(account):
    #code to do with successful password

def failed_password(account):
    #code to do with failed password
def main()
Password('1234', successful_password, failed_password, account_info)[/python]

In a GUI program you don't have a main function or body of code that contains all the program logic. Instead you break the logic up into a bunch of functions (or objects and methods) that are bound to GUI controls. In the pseudo example above the entry widget controls if and when the successful password code or the failed password code executes.
Reply
#10
I understand and thank you again for your information about return values in tkinter.So,now I'm thinking when the password that the user gives is correct ,I want to delete the whole screen(buttons ,entry,labels,etc) to continue and build my app.
I tried:
button_ok.destroy()
button_cancel.destroy()
,but I receive an error.
I searched in Google, but I didn't find anything.So,how can I destroy labels buttons and entry?
I use place() method as you can see in my first post.
Thanks again.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  return a variable from a function snakes 3 909 Apr-09-2021, 06:47 PM
Last Post: snakes
  tkinter get function finndude 2 692 Mar-02-2021, 03:53 PM
Last Post: finndude
  Using Tkinter inside function not working Ensaimadeta 3 894 Dec-23-2020, 02:57 PM
Last Post: deanhystad
  function in new window (tkinter) Dale22 7 1,033 Nov-24-2020, 11:28 PM
Last Post: Dale22
Star [Tkinter] How to perform math function in different page of Tkinter GUI ravaru 2 1,229 Oct-23-2020, 05:46 PM
Last Post: deanhystad
  Call local variable of previous function from another function with Python3 & tkinter Hannibal 5 1,259 Oct-12-2020, 09:16 PM
Last Post: deanhystad
  Tkinter menu font size -method to change tonycat 2 2,307 Oct-11-2020, 02:43 AM
Last Post: tonycat
  tkinter get method is not accepting value when called by function jagasrik 1 773 Sep-16-2020, 05:28 AM
Last Post: Yoriz
  tkinter get method is not accepting value jagasrik 4 758 Sep-15-2020, 05:41 PM
Last Post: jagasrik
  [Tkinter] Use function from other class (Tkinter) zarize 8 1,472 Aug-17-2020, 09:47 AM
Last Post: zarize

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020