添加菜单
This commit is contained in:
parent
bc0f82125c
commit
8046c09321
Binary file not shown.
|
@ -0,0 +1,265 @@
|
|||
import json
|
||||
import tkinter
|
||||
import sys
|
||||
from tkinter import ttk
|
||||
from tkinter import font as tkfont
|
||||
try:
|
||||
import color_tmpl
|
||||
except ImportError:
|
||||
from magictk import color_tmpl
|
||||
try:
|
||||
import photoload
|
||||
except ImportError:
|
||||
from magictk import photoload
|
||||
|
||||
transcolor = "#41342F"
|
||||
usetrans = sys.platform.startswith('win')
|
||||
|
||||
|
||||
def set_font():
|
||||
global use_font
|
||||
font_family = ["Helvetica Neue", "Helvetica", "PingFang SC", "Hiragino Sans GB",
|
||||
"Microsoft YaHei",
|
||||
"微软雅黑",
|
||||
"Arial", "sans-serif"]
|
||||
t_family = tkfont.families(root=None, displayof=None)
|
||||
for i in font_family:
|
||||
if i in t_family:
|
||||
use_font = i
|
||||
break
|
||||
else:
|
||||
print("Unknown font")
|
||||
|
||||
|
||||
class MenuObjs:
|
||||
def __init__(self):
|
||||
self.menu_lst = []
|
||||
self.menu_func = []
|
||||
self.menu_effect = []
|
||||
|
||||
def first_action(self, menuobj):
|
||||
pass
|
||||
|
||||
def addmenu(self, name, func, effect={}):
|
||||
self.menu_lst.append(name)
|
||||
self.menu_func.append(func)
|
||||
self.menu_effect.append(effect)
|
||||
|
||||
|
||||
class Menu:
|
||||
__relh = 0
|
||||
__color_bd = "border_base"
|
||||
__color_bg = "background"
|
||||
__color_fg = "primary"
|
||||
__color_fg1 = "primary_light"
|
||||
__color_fg2 = "primary_light2"
|
||||
color = color_tmpl.default_color
|
||||
__close_mode = 0
|
||||
|
||||
__last_highlight = 0
|
||||
__y_move = 0
|
||||
___last_move = 1
|
||||
___last_highlight = 0
|
||||
ht = 12
|
||||
lt = 22
|
||||
ft = 34
|
||||
|
||||
def __anim(self, *args):
|
||||
if (self.__close_mode == 0):
|
||||
if (self.__relh != self.h):
|
||||
if (self.h-self.__relh <= 1):
|
||||
self.__relh = self.h
|
||||
elif (self.h-self.__relh > 32):
|
||||
self.__relh += 32
|
||||
else:
|
||||
self.__relh += (self.h-self.__relh) >> 1
|
||||
self.toplevel.geometry(
|
||||
f"{self.w}x{self.__relh}+{self.x}+{self.y}")
|
||||
elif self.__close_mode == 1:
|
||||
if (self.__relh != 0):
|
||||
if (self.__relh-0 <= 1):
|
||||
self.toplevel.destroy()
|
||||
self.__close_mode = 2
|
||||
return
|
||||
elif (self.__relh-0 > 32):
|
||||
self.__relh -= 32
|
||||
else:
|
||||
self.__relh -= (self.__relh-0) >> 1
|
||||
self.toplevel.geometry(
|
||||
f"{self.w}x{self.__relh}+{self.x}+{self.y}")
|
||||
else:
|
||||
return -1
|
||||
if (self.___last_move != self.__y_move):
|
||||
n = 0
|
||||
for i in self.__itemsf:
|
||||
self.canvas.moveto(i, 24, n*self.ft+self.ht +
|
||||
self.__y_move+(self.ft-self.font[1]*2.5)//2)
|
||||
n += 1
|
||||
n = 0
|
||||
for i in self.__items:
|
||||
self.canvas.moveto(i, 2, n*self.ft+self.ht-4 +
|
||||
self.__y_move)
|
||||
n += 1
|
||||
self.___last_move = self.__y_move
|
||||
n = 0
|
||||
for i in self.menuobj.menu_effect:
|
||||
if (len(i) != 0):
|
||||
self.canvas.itemconfigure(
|
||||
self.__itemsf[n], justify=tkinter.LEFT, **i)
|
||||
self.canvas.moveto(self.__itemsf[n], 24, n*self.ft+self.ht +
|
||||
self.__y_move+(self.ft-self.font[1]*2.5)//2)
|
||||
else:
|
||||
self.canvas.itemconfigure(
|
||||
self.__itemsf[n], justify=tkinter.LEFT, fill=self.color["regular_text"], font=self.font)
|
||||
self.canvas.moveto(self.__itemsf[n], 24, n*self.ft+self.ht +
|
||||
self.__y_move+(self.ft-self.font[1]*2.5)//2)
|
||||
n += 1
|
||||
|
||||
def __mouse_move(self, event: tkinter.Event):
|
||||
y = event.y
|
||||
self.__last_highlight = max(
|
||||
-1, min(len(self.__items), int((y-self.ht-self.__y_move)//self.ft)))
|
||||
if (self.__last_highlight == -1 or self.__last_highlight >= len(self.__items)):
|
||||
if (self.___last_highlight != -2):
|
||||
self.canvas.itemconfig(
|
||||
self.__items[self.___last_highlight], fill=self.color["background"])
|
||||
self.___last_highlight = -2
|
||||
elif (self.___last_highlight != self.__last_highlight):
|
||||
self.canvas.itemconfig(
|
||||
self.__items[self.__last_highlight], fill=self.color["placeholder_light"])
|
||||
self.canvas.itemconfig(
|
||||
self.__items[self.___last_highlight], fill=self.color["background"])
|
||||
self.___last_highlight = self.__last_highlight
|
||||
|
||||
def close(self, *args):
|
||||
self.__close_mode = 1
|
||||
if (self.__closecallback is not None):
|
||||
self.__closecallback(self)
|
||||
|
||||
def __init__(self, root, menuobj: MenuObjs, w=200, h=300, x=100, y=300, color_list: None | dict = None, closeonleave=True, fontsize=10, closecallback=None):
|
||||
set_font()
|
||||
self.__closecallback = closecallback
|
||||
self.font = (use_font, fontsize)
|
||||
self.__items = []
|
||||
self.__itemsf = []
|
||||
self.menuobj = menuobj
|
||||
self.w = w
|
||||
self.h = h
|
||||
self.x = x
|
||||
self.y = y
|
||||
if (color_list is not None):
|
||||
self.color = color_list
|
||||
self.toplevel = tkinter.Toplevel(bg=transcolor)
|
||||
self.toplevel.wm_attributes('-topmost', True)
|
||||
self.toplevel.overrideredirect(True)
|
||||
self.toplevel.geometry(f"{self.w}x{self.__relh}+{self.x}+{self.y}")
|
||||
if (usetrans):
|
||||
self.toplevel.wm_attributes('-transparentcolor', transcolor)
|
||||
self.root = root
|
||||
self.canvas = tkinter.Canvas(
|
||||
self.toplevel, bg=self.color["background"], highlightthickness=0, width=self.w+1, height=self.h+1)
|
||||
self.canvas.place(x=-1, y=-1)
|
||||
self.root.anim.append(self.__anim)
|
||||
self.toplevel.focus()
|
||||
self.__draw_menu()
|
||||
self.__draws()
|
||||
|
||||
if (closeonleave):
|
||||
self.toplevel.bind("<FocusOut>", self.close)
|
||||
if (not usetrans):
|
||||
self.toplevel.bind("<Leave>", self.close)
|
||||
|
||||
self.canvas.bind("<Motion>", self.__mouse_move)
|
||||
self.__bind_scroll()
|
||||
self.canvas.bind("<ButtonRelease-1>", self.__click)
|
||||
self.toplevel.bind_all("<Escape>", self.close)
|
||||
self.toplevel.bind_all("<Return>", self.__click)
|
||||
|
||||
def __draw_menu(self):
|
||||
n = 0
|
||||
for i in self.menuobj.menu_lst:
|
||||
self.__items.append(self.canvas.create_rectangle(
|
||||
2, n*self.ft+self.ht, self.w, (n+1)*self.ft+self.ht, fill=self.color["background"], width=0))
|
||||
self.__itemsf.append(self.canvas.create_text(
|
||||
10, n*self.ft+self.ht, text=i, font=self.font, justify=tkinter.LEFT, fill=self.color["regular_text"]))
|
||||
n += 1
|
||||
|
||||
def __draw_corner(self, r_x, r_y, x, y, **kwargs):
|
||||
border_info = json.loads(photoload.loadres("menuborder"))
|
||||
y_n = 0
|
||||
for i in border_info:
|
||||
x_n = 0
|
||||
for j in i:
|
||||
if (r_x == 0):
|
||||
px = x+x_n+1
|
||||
else:
|
||||
px = x+4-x_n-1
|
||||
if (r_y == 0):
|
||||
py = y+y_n+1
|
||||
else:
|
||||
py = y+4-y_n-1
|
||||
if (j < 0):
|
||||
lcolor = -j
|
||||
else:
|
||||
lcolor = j
|
||||
if (lcolor == 255):
|
||||
x_n += 1
|
||||
continue
|
||||
if (j < 0):
|
||||
if (usetrans):
|
||||
g_color = transcolor
|
||||
else:
|
||||
g_color = self.color["background"]
|
||||
else:
|
||||
g_color = color_tmpl.mix_color(
|
||||
self.color["background"], self.color[self.__color_bd], int((1-lcolor/255)*1000)/1000)
|
||||
self.canvas.create_rectangle(
|
||||
px, py, px, py, width=0, fill=g_color)
|
||||
x_n += 1
|
||||
y_n += 1
|
||||
|
||||
def __draws(self):
|
||||
self.__draw_corner(0, 0, 0, 0)
|
||||
self.__draw_corner(1, 0, self.w-4+1, 0)
|
||||
self.__draw_corner(0, 1, 0, self.h-4+1)
|
||||
self.__draw_corner(1, 1, self.w-4+1, self.h-4+1)
|
||||
self.canvas.create_line(
|
||||
1, 5, 1, self.h-3, width=1, fill=self.color[self.__color_bd])
|
||||
self.canvas.create_line(
|
||||
5, 1, self.w-3, 1, width=1, fill=self.color[self.__color_bd])
|
||||
self.canvas.create_line(
|
||||
self.w, 5, self.w, self.h-3, width=1, fill=self.color[self.__color_bd])
|
||||
self.canvas.create_line(
|
||||
5, self.h, self.w-3, self.h, width=1, fill=self.color[self.__color_bd])
|
||||
|
||||
def __bind_scroll(self):
|
||||
def scrollwheel(event: tkinter.Event, setdelta=None):
|
||||
if (setdelta is None):
|
||||
delta = event.delta
|
||||
else:
|
||||
delta = setdelta
|
||||
if sys.platform.startswith('win'):
|
||||
delta //= 120
|
||||
if delta > 0:
|
||||
self.__y_move = min(0, self.__y_move+delta)
|
||||
else:
|
||||
self.__y_move = max(
|
||||
-max(0, len(self.__items)*self.ft+self.ht-self.h), self.__y_move+delta)
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
self.toplevel.bind_all("<MouseWheel>", scrollwheel)
|
||||
elif sys.platform.startswith('darwin'):
|
||||
self.toplevel.bind_all("<MouseWheel>", scrollwheel)
|
||||
else:
|
||||
self.toplevel.bind_all(
|
||||
"<Button-4>", lambda event: scrollwheel(event, 8))
|
||||
self.toplevel.bind_all(
|
||||
"<Button-5>", lambda event: scrollwheel(event, -8))
|
||||
|
||||
def __click(self, event):
|
||||
click_item = max(
|
||||
-1, min(len(self.__items), int((event.y-self.ht-self.__y_move)//self.ft)))
|
||||
if (click_item == -1 or self.__last_highlight >= len(self.__items)):
|
||||
return
|
||||
self.close()
|
||||
self.menuobj.menu_func[click_item](self, click_item)
|
|
@ -0,0 +1,26 @@
|
|||
[
|
||||
[
|
||||
-1,
|
||||
-1,
|
||||
64,
|
||||
14
|
||||
],
|
||||
[
|
||||
-1,
|
||||
34,
|
||||
155,
|
||||
245
|
||||
],
|
||||
[
|
||||
64,
|
||||
155,
|
||||
255,
|
||||
255
|
||||
],
|
||||
[
|
||||
14,
|
||||
245,
|
||||
255,
|
||||
255
|
||||
]
|
||||
]
|
Loading…
Reference in New Issue