I'm having trouble getting a timer (loop or anything) running when the tkinter window is withdrawn or not on top of other windows. The functionality of this is like a small screen saver, start the program, have icon displayed, click show the full screen image appears, if triple click it disappears and goes back to system tray. All of that works, however the timer in the after method only works if the window is displayed, and I want it to work when it's not displayed so it can display it after a period of inactivity (10 secs for testing).
How can I get the inactivity timer working when the tkinter window isn't displayed?
from tkinter import *
from ctypes import Structure, windll, c_uint, sizeof, byref
import time
import pystray
from PIL import Image, ImageTk
class LASTINPUTINFO(Structure):
_fields_ = [
('cbSize', c_uint),
('dwTime', c_uint),
]
def get_idle_duration():
lastInputInfo = LASTINPUTINFO()
lastInputInfo.cbSize = sizeof(lastInputInfo)
windll.user32.GetLastInputInfo(byref(lastInputInfo))
millis = windll.kernel32.GetTickCount() - lastInputInfo.dwTime
return millis / 1000.0
class FS_Display:
def __init__(self):
self.root = Tk()
self.root.title("FS Display")
self.root.bind("<Triple-1>", self.end_fullscreen)
self.root.bind("<Escape>", self.end_fullscreen)
self.root.protocol('WM_DELETE_WINDOW', self.end_fullscreen)
self.end_fullscreen()
def end_fullscreen(self, event=None):
self.root.withdraw()
self.image = Image.open("favicon.png")
self.menu = (pystray.MenuItem('Quit', self.quit), pystray.MenuItem('Show', self.show_fullscreen))
self.icon = pystray.Icon("name", self.image, "FS Display", self.menu)
self.icon.run()
def show_fullscreen(self, event=None):
self.root.attributes("-fullscreen", True)
self.icon.stop()
self.root.deiconify()
def quit(self, event=None):
self.icon.stop()
self.root.destroy()
def idle_check(self, event=None):
GetLastInputInfo = int(get_idle_duration())
print(GetLastInputInfo)
if GetLastInputInfo == 10:
self.show_fullscreen()
self.root.after(1000, self.idle_check)
if __name__ == '__main__':
fs = FS_Display()
main_image = Image.open("D:black_background.png")
photo = ImageTk.PhotoImage(main_image)
Label(fs.root, image=photo).pack()
fs.root.after(1000, fs.idle_check)
fs.root.mainloop()
CodePudding user response:
The timer and after code actually do work. The psytray code icon.run()
blocks until icon.stop()
. You can give icon.run()
a callback that will allow it to run a timer. The downside is the icon menu options don't work during a callback loop.