-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
180 lines (143 loc) · 5.54 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
"""
A simple program using pystray to expose the possibility of a Flet app being reduced to a System Tray icon.
This program has been tested only on Windows. I hope it works on your device too. Let me know if not.
"""
import pystray # pip install pystray | https://pystray.readthedocs.io
import flet as ft
from PIL import Image # pip install pillow
# the image to be displayed in the tray
tray_image = Image.open("tray_img.png")
p: ft.Page
def exit_app(icon, query):
"""
Callback for the click of the Last menu item.
:param icon: The object of the tray icon
:param query: The text that is displayed on the - pressed - menu item
:type icon: pystray.Icon
"""
button_clicked(None)
icon.stop() # stop the tray icon loop/display
p.window_destroy() # close our window
print("The App was closed/exited successfully!")
def other_item_clicked(icon, query):
"""
Callback for the click of a non-default menu item. (the two in the middle)
:param icon: The object of the tray icon
:param query: The text that is displayed on the - pressed - menu item
:type icon: pystray.Icon
"""
button_clicked(None)
print("A Non-Default button was pressed.")
def default_item_clicked(icon, query):
"""
Callback for the click of the default menu item. (the first one)
:param icon: The object of the tray icon
:param query: The text that is displayed on the - pressed - menu item
:type icon: pystray.Icon
"""
button_clicked(None)
icon.visible = False
p.window_skip_task_bar = False
p.window_maximized = True
p.update()
print("Default button was pressed.")
def menu_item_clicked(icon, query):
"""
A 3-in-1 callback to replace the above three functions.
It uses if statements and runs some code based on the query(displayed text) of the clicked menu item.
:param icon: The object of the tray icon
:param query: The text that is displayed on the - pressed - menu item
:type icon: pystray.Icon
"""
button_clicked(None)
if str(query) == "Open App":
icon.visible = False
p.window_skip_task_bar = False
p.window_maximized = True
p.update()
print("Default button was pressed.")
elif str(query) == "Close App":
icon.stop()
p.window_close()
print("The App was closed/exited successfully!")
else:
print("A Non-Default button was pressed.")
def my_setup(icon):
"""
A custom setup function;
Copied from Pystray docs: An optional callback to execute in a separate thread once the loop has started.
It is passed the icon as its sole argument.
If not specified, a simple setup function setting visible to True is used.
If you specify a custom setup function, you must explicitly set this attribute.
:type icon: pystray.Icon
"""
# set the visibility of the tray icon at program start to be False
icon.visible = False
tray_icon = pystray.Icon(
name="Test",
icon=tray_image,
title="Flet in tray",
menu=pystray.Menu(
pystray.MenuItem(
"Open App",
default_item_clicked, # alternative/broader callback: menu_item_clicked
default=True # set as default menu item
),
pystray.MenuItem(
"Go Nowhere 1",
other_item_clicked # alternative/broader callback: menu_item_clicked
),
pystray.MenuItem(
"Go Nowhere 2",
other_item_clicked # alternative/broader callback: menu_item_clicked
),
pystray.MenuItem(
"Close App",
exit_app # alternative/broader callback: menu_item_clicked
)
),
visible=False,
)
def button_clicked(e):
"""
It adds a new text element to the page;
indicating that the attached button was directly or indirectly(through the tray's menu items) pressed.
"""
p.add(ft.Text("Button event handler was triggered!"))
def on_window_event(e):
"""
When should the tray icon be made visible or not.
"""
if e.data == "minimize":
# if the window is minimized, we make the icon visible, and remove our app from the taskbar/dock.
tray_icon.visible = True
p.window_skip_task_bar = True
elif e.data == "restore":
# if the window is maximized/restored, we make the icon not visible, and add our app back to the taskbar/dock.
tray_icon.visible = False
p.window_skip_task_bar = False
elif e.data == "close":
tray_icon.stop()
e.page.window_destroy()
p.update()
def main(page):
# make the page available outside this function using p
global p
p = page
page.on_window_event = on_window_event
page.window_prevent_close = True
page.title = "Flet in the sys-tray"
page.add(
ft.Text("- Minimize this app to see in the tray. \n"
"- Then press the flet tray icon button to make the window visible again."),
ft.ElevatedButton("Button with 'click' event", on_click=button_clicked)
)
# pystray docs: https://pystray.readthedocs.io/en/latest/faq.html#i-am-trying-to-integrate-with-a-framework-but-run-detached-does-not-work
# run_detached() below is strictly necessary only on macOS! It allows integrating pystray with other libraries
# Call this method before entering the mainloop of the other library.
tray_icon.run_detached(setup=my_setup)
"""
# For other platforms, it is possible to just launch the icon mainloop in a thread:
threading.Thread(target=icon.run, args=([my_setup])).start()
"""
ft.app(target=main) # cannot obviously run in web browser!!