AD WAN
AD WAN

Reputation: 1474

How to set idle time-out for your GUI in Tkinter (PYTHON 3.6.1)

I want my GUI to ask for login again after been left idle for 5 minutes when you login but the root window should stay when tick the checkbutton.

Challenges:
As soon as I run the script, the messagebox parsed under "session_ends" function pops-up.

When I type the the name and password into the entry widget and I tick the checkbutton, another window also pops-up.

import tkinter as tk
import sys
from tkinter import messagebox


name=("user")
password=("python3")

def login_in():
    if entry1.get() == name and entry2.get() == password:
        root.deiconify()
        log.destroy()
    else:
        messagebox.showerror("error","login Failed")
        entry1.set("")   # This clears entry1
        entry2.set("")   # this clears entry2

def close():
    log.destroy() #Removes toplevel window
    root.destroy() #Removes  root window
    sys.exit() #Ends the script

def session_end():
    messagebox.showinfo("session expired","kindly login again")

def continue_session():
    root.deiconify()

root=tk.Tk()
log = tk.Toplevel() #

root.geometry("350x350")
log.geometry("200x200")

entry1 = tk.Entry(log) #Username entry
entry2 = tk.Entry(log) #Password entry
check = tk.Checkbutton(log,text="keep me 
login",command=continue_session)#root should stay when you tick checkbutton
button1 = tk.Button(log, text="Login", command=login_in) #Login button
button2 = tk.Button(log, text="Cancel", command=close) #Cancel button
label1 = tk.Label(root, text="This main ui after being idle for 5 minutes \n 
   You need to login for the main ui to open")


entry1.pack()
entry2.pack()
check.pack()
button1.pack()
button2.pack()
label1.pack()

root.withdraw()
root.after(5000,session_end())
root.mainloop()

EDIT: with the above code have edited it with the answer @Bryan Oakley provided but is the idle timeout the work after 5 minute being idle

import tkinter as tk
import sys

name=("user")
password=("python3")

after_id=None

def reset_timer(event=None):
    global after_id
    if after_id is not None:
        root.after_cancel(after_id)
        after_id = root.after(300000,session_end)


def login_in():
    if entry1.get() == name and entry2.get() == password:
        root.deiconify()
        log.destroy()
    else:
        messagebox.showerror("error","login Failed")


def close():
    log.destroy() #Removes toplevel window
    root.destroy() #Removes  root window
    sys.exit() #Ends the script


def session_end():
    messagebox.showinfo("session expired","kindly login again")

def continue_session():
    if after_id is not None:
    root.deiconify()


def print_some():
    print("This is idle timeout")


root=tk.Tk()
log = tk.Toplevel() #

root.geometry("350x350")
log.geometry("200x200")

entry1 = tk.Entry(log) #Username entry
entry2 = tk.Entry(log) #Password entry
check = tk.Checkbutton(log,text="keep me 
login",command=continue_session)#root should stay when you tick checkbutton
button1 = tk.Button(log, text="Login", command=login_in) #Login button
button2 = tk.Button(log, text="Cancel", command=close) #Cancel button
label1 = tk.Label(root, text="This main ui after being idle for 5 minutes \n 
You need to login for the main ui\to open")
print_button = tk.Button(root,text="print",command=print_some).pack()


entry1.pack()
entry2.pack()
check.pack()
button1.pack()
button2.pack()
label1.pack()

root.withdraw()
root.bind_all("<Any-KeyPress>",reset_timer)
root.bind_all("<Any-ButtonPress>",reset_timer)
root.mainloop()

Upvotes: 0

Views: 3467

Answers (2)

Melvin Paul Jacob
Melvin Paul Jacob

Reputation: 1

time_out = 30000
def reset_timer(event=None):
    global time_out
    if event is not None:
        time_out = 30000
    else:
        pass

def reduce_time_out():
   global time_out
   time_out = time_out-1000
   print(time_out)
   root.after(1000,reduce_time_out)
   if time_out ==0:
       log.destroy() #Removes toplevel window
       root.destroy() #Removes  root window
       messagebox.showinfo("session expired","kindly login again")
       sys.exit()

root.after(1000,reduce_time_out)
root.bind_all("<Any-KeyPress>",reset_timer)
root.bind_all("<Any-ButtonPress>",reset_timer)

Upvotes: 0

Bryan Oakley
Bryan Oakley

Reputation: 385950

How to set idle time-out for your GUI in Tkinter (PYTHON 3.6.1)

A simple solution is to create a function that will end a session, and then schedule that function to run in the future. You are attempting this, but you are calling after incorrectly.

The key to making this be a true idle timeout is to know when the user is "idle". A simple solution is to make a global binding for <Any-KeyPress> and <Any-ButtonPress>

The first thing is to create a global or instance variable to remember the id of the command we're running with after:

after_id = None

The next step is to create a function to reset the timer. It needs to accept an event since one is automatically passed by tkinter. However, we want to be able to call the function directly so we'll make it optional.

def reset_timer(event=None):
    global after_id
    if after_id is not None:
        root.after_cancel(after_id)
    after_id = root.after(5000, session_end)

To start the session, we can directly call the function:

reset_timer()

Next, we can set up bindings to reset the timer on user activity. In this case I'll define activity as any button or key press. We do it like this:

root.bind_all("<Any-KeyPress>", reset_timer)
root.bind_all("<Any-ButtonPress>", reset_timer)

Upvotes: 2

Related Questions