1- #!/usr/bin/python3
1+ """一个基于tkinter的,用于显示minecraft风格的toast的库
2+ 目前被CamMoitor使用
3+
4+ 这个库与Mojang,Microsoft没有任何关系,且在这里不使用client.jar,.minecraft/assets文件夹下的任何文件
5+ Toast纹理来自VanillaXBR,基于CC-BY-NC-4.0许可证开源
6+ 若遇到了相关的许可证问题,请第一时间提交issue并加上 版权或许可证问题 标签
7+
8+ VanillaXBR: https://modrinth.com/resourcepack/vanillaxbr
9+ CC-BY-NC-4.0: https://creativecommons.org/licenses/by-nc/4.0/legalcode
10+ 提交issue: https://github.com/SystemFileB/mctoast/issues """
11+
212import tkinter as tk
313import os
414import time
1323ADVANCEMENT = pathjoin (path , "assets" ,"mctoast" ,"textures" ,"advancement.png" )
1424RECIPE = pathjoin (path , "assets" ,"mctoast" ,"textures" ,"recipe.png" )
1525SYSTEM = pathjoin (path , "assets" ,"mctoast" ,"textures" ,"system.png" )
26+ RETURN_PHOTOIMAGE = 0
27+ RETURN_IMAGE = 1
28+ RETURN_BYTE = 2
1629
17- def generate_image (toast , image_path , text1 , color1 , text2 , color2 ):
18- """生成Toast图片"""
19- # 打开背景图片并缩放
20- background_image = Image .open (toast ).resize ((320 , 64 ))
21-
22- # 打开小图片并缩放
23- if image_path :
24- small_image = Image .open (image_path ).resize ((30 , 30 ))
25- background_image .paste (small_image , (17 , 17 ))
26-
27- # 创建一个绘图对象
28- draw = ImageDraw .Draw (background_image )
29-
30- # 加载字体
31- font = ImageFont .truetype (pathjoin (path ,"assets" ,"mctoast" ,"fonts" ,"unifont.otf" ), 15 )
32-
33- if toast == SYSTEM :
34- if text1 and color1 :
35- draw .text ((34 , 13 ), text1 , fill = color1 , font = font )
36- if text2 and color2 :
37- draw .text ((34 , 35 ), text2 , fill = color2 , font = font )
38- else :
39- # 在指定位置绘制文字
40- if text1 and color1 :
41- draw .text ((60 , 13 ), text1 , fill = color1 , font = font )
42- if text2 and color2 :
43- draw .text ((60 , 35 ), text2 , fill = color2 , font = font )
44-
45- # 将 Pillow 图片转换为 PhotoImage
46- return ImageTk .PhotoImage (background_image )
30+ def generate_image (toast :str , image_path :str , text1 :str , color1 :str , text2 :str , color2 :str , return_mode = RETURN_IMAGE ):
31+ """生成Toast图片
32+ toast:str 背景图片(ADVANCEMENT,RECIPE,SYSTEM)
33+ image_path:str 图片路径(对应原版的物品位置)
34+ text1:str 第一行文本
35+ color1:str 第一行文本颜色
36+ text2:str 第二行文本
37+ color2:str 第二行文本颜色
38+ return_mode:int 返回模式(RETURN_IMAGE,RETURN_PHOTOIMAGE,RETURN_BYTE)
39+ """
40+ # 打开背景图片并缩放
41+ background_image = Image .open (toast )
42+ if background_image .mode != 'RGBA' :
43+ background_image = background_image .convert ("RGBA" )
44+
45+ # 打开小图片并缩放
46+ if image_path :
47+ small_image = Image .open (image_path ).resize ((57 , 57 ),Image .Resampling .NEAREST )
48+ # 确保图片为RGBA模式
49+ if small_image .mode != 'RGBA' :
50+ small_image = small_image .convert ("RGBA" )
51+ background_image .paste (small_image , (34 , 33 ),mask = small_image )
52+
53+ # 创建一个绘图对象
54+ draw = ImageDraw .Draw (background_image )
55+
56+ # 加载字体
57+ font = ImageFont .truetype (pathjoin (path , "assets" , "mctoast" , "fonts" , "unifont.otf" ), 30 )
58+
59+ if toast == SYSTEM :
60+ if text1 and color1 :
61+ draw .text ((68 , 26 ), text1 , fill = color1 , font = font )
62+ if text2 and color2 :
63+ draw .text ((68 , 70 ), text2 , fill = color2 , font = font )
64+ else :
65+ # 在指定位置绘制文字
66+ if text1 and color1 :
67+ draw .text ((120 , 26 ), text1 , fill = color1 , font = font )
68+ if text2 and color2 :
69+ draw .text ((120 , 70 ), text2 , fill = color2 , font = font )
70+
71+ # 将 Pillow 图片转换为 PhotoImage
72+ if return_mode == RETURN_IMAGE :
73+ return background_image .resize ((320 , 64 ),Image .Resampling .NEAREST )
74+ elif return_mode == RETURN_BYTE :
75+ return background_image .resize ((320 , 64 ),Image .Resampling .NEAREST ).tobytes ()
76+ else :
77+ return ImageTk .PhotoImage (background_image .resize ((320 , 64 ),Image .Resampling .NEAREST ))
4778
4879class ToastWindowUI :
80+ """Toast界面类"""
4981 def __init__ (self , master = None , data_pool = None ):
5082 # build ui
5183 self .root = tk .Tk (master )
@@ -76,7 +108,7 @@ def new_toast(self, toast=ADVANCEMENT, image_path=None, text1="一个弹窗", co
76108 for i in range (5 ):
77109 if toasts [i ] == None :
78110 # 使用 Pillow 生成图片
79- photo = generate_image (toast , image_path , text1 , color1 , text2 , color2 )
111+ photo = generate_image (toast , image_path , text1 , color1 , text2 , color2 , RETURN_PHOTOIMAGE )
80112 self .root .deiconify ()
81113 toasts [i ] = self .canvas .create_image (320 , i * 64 , anchor = "nw" , image = photo )
82114 event .set ()
@@ -132,36 +164,37 @@ def set_no_focus(self):
132164
133165window = None
134166def _init ():
167+ """别调用"""
135168 global window
136169 window = ToastWindowUI ()
137170 window .main ()
138171
139172def init ():
173+ """初始化窗口"""
140174 thread .start_new_thread (_init ,())
141175 while type (window )!= ToastWindowUI :
142176 pass
143177
144- def new_toast (toast = ADVANCEMENT , image_path = None , text1 = "一个弹窗" , color1 = "yellow" , text2 = "MCToast示例" , color2 = "white" ):
178+ def new_toast (toast = ADVANCEMENT , image_path :str = None , text1 = "一个弹窗" , color1 = "yellow" , text2 = "MCToast示例" , color2 = "white" ):
179+ """新弹窗
180+ toast:str 背景图片(ADVANCEMENT,RECIPE,SYSTEM)
181+ image_path:str 图片路径(对应原版的物品位置)
182+ text1:str 第一行文本
183+ color1:str 第一行文本颜色
184+ text2:str 第二行文本
185+ color2:str 第二行文本颜色"""
145186 global window
146- #thread.start_new_thread(window.new_toast,(toast, image_path, text1, color1, text2, color2))
147- #window.new_toast(toast, image_path, text1, color1, text2, color2)
148187 e = Event ()
149188 t = Thread (target = window .new_toast ,args = (toast , image_path , text1 , color1 , text2 , color2 , e ))
150189 t .start ()
151190 e .wait ()
152191
153192def quit ():
193+ """退出(好像根本不需要)"""
154194 global window
155195 window .stop ()
156196
157197def wait_no_toast ():
198+ """等待所有toast消失"""
158199 global window
159- window .wait_no_toast ()
160-
161- if __name__ == "__main__" :
162- # demo
163- init ()
164- for i in range (1 ,11 ):
165- new_toast (toast = SYSTEM , text2 = f"第{ i } " )
166- time .sleep (0.5 )
167- wait_no_toast ()
200+ window .wait_no_toast ()
0 commit comments