简体   繁体   中英

Running a Tkinter window and PysTray Icon together

I'm building a tkinter gui project and i'm looking for ways to run a tray icon with the tkinter window.
I found Pystray library that does it, But now i'm trying to figure it out how to use this library (tray Icon) together with tkinter window,
I set it up when the user exit winodw it's only will withdraw window:
self.protocol('WM_DELETE_WINDOW', self.withdraw)
I want to bring it back with the tray icon.. anyone know how to do it?
EDIT:untill now I just wrote this code so far (they're not running together but it's also fine):

from pystray import MenuItem as item
import pystray
from PIL import Image
import tkinter as tk

def quit_window(icon, item):
    icon.stop()
    #window.destroy()

def show_window(icon, item):
    icon.stop()
    #window.deiconify()

def withdraw_window(window):    
    window.withdraw()
    image = Image.open("image.ico")
    menu = (item('Quit', quit_window), item('Show', show_window))
    icon = pystray.Icon("name", image, "title", menu)
    icon.run()

def main():
    window = tk.Tk() 
    window.title("Welcome")
    window.protocol('WM_DELETE_WINDOW', lambda: withdraw_window(window))
    window.mainloop()
main()

Finally I figure it out,
Now I just need to combine this with my main code, I hope this code will help to other people too...

from pystray import MenuItem as item
import pystray
from PIL import Image
import tkinter as tk

window = tk.Tk()
window.title("Welcome")

def quit_window(icon, item):
    icon.stop()
    window.destroy()

def show_window(icon, item):
    icon.stop()
    window.after(0,window.deiconify)

def withdraw_window():  
    window.withdraw()
    image = Image.open("image.ico")
    menu = (item('Quit', quit_window), item('Show', show_window))
    icon = pystray.Icon("name", image, "title", menu)
    icon.run()

window.protocol('WM_DELETE_WINDOW', withdraw_window)
window.mainloop()

Thanks to Oshers solution, I adapted it into my own project.

One issue I fixed was that you could only hide the main window once, then the loop would crash. With this solution, it has no limit.

import tkinter as tk
from PIL import Image

import pystray


class Gui():

    def __init__(self):
        self.window = tk.Tk()
        self.image = Image.open("./assets/icons/ready.png")
        self.menu = (
            pystray.MenuItem('Show', self.show_window),
            pystray.MenuItem('Quit', self.quit_window)
            )
        self.window.protocol('WM_DELETE_WINDOW', self.withdraw_window)
        self.window.mainloop()


    def quit_window(self):
        self.icon.stop()
        self.window.destroy()


    def show_window(self):
        self.icon.stop()
        self.window.protocol('WM_DELETE_WINDOW', self.withdraw_window)
        self.window.after(0, self.window.deiconify)


    def withdraw_window(self):
        self.window.withdraw()
        self.icon = pystray.Icon("name", self.image, "title", self.menu)
        self.icon.run()


if __name__ in '__main__':
    Gui()

For anyone wanting to run both at the same time it's possible to run pystray in it's own thread by using run_detached() instead of run() . Based on Osher's answer here's an example that keeps the icon in the system tray even after closing the window.

from pystray import MenuItem as item
import pystray
from PIL import Image
import tkinter as tk


def quit_window(icon, item):
    icon.visible = False
    icon.stop()
    window.quit()


def show_window(icon, item):
    window.after(0, window.deiconify)


def withdraw_window():
    window.withdraw()


window = tk.Tk()
window.title("Welcome")
image = Image.open("free.ico")

menu = (item('Quit', quit_window), item('Show', show_window))
icon = pystray.Icon("name", image, "title", menu)
icon.run_detached()
window.protocol('WM_DELETE_WINDOW', withdraw_window)
window.mainloop()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM