0

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()
AD WAN
  • 1,414
  • 2
  • 15
  • 28
  • Part of the problem is that you are using `after` incorrectly. What you're doing is the same as `session_end(); root.after(5000, None)`. See http://stackoverflow.com/q/5767228/7432 – Bryan Oakley Aug 21 '17 at 14:09

2 Answers2

2

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)
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • @ Bryan Oakley i will try what you've suggested and update you with the results.Many thanks. – AD WAN Aug 21 '17 at 14:50
  • have done what you suggested and added "print Button" to my main window so that after being idle for 5 minute and i click the button the session_end messsagebox will ask me to login again before i can work in my main window. – AD WAN Aug 23 '17 at 09:55
  • Have posted what you sugested.If the is any improper arrangement you can point it out for me to achieve the result.Still looking for best way to do this.Thanks – AD WAN Aug 23 '17 at 10:11
  • I didn't know how to post the code the code back for references ,that is why i posted as an answer. have delete it.Thanks for the corrections – AD WAN Aug 23 '17 at 13:20
0
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)