优化select

This commit is contained in:
cxykevin 2024-04-13 19:22:12 +08:00
parent d13aaf5278
commit db3f0b2445
3 changed files with 80 additions and 229 deletions

View File

@ -121,7 +121,7 @@ class Button:
def place(self, *args, **kwargs): def place(self, *args, **kwargs):
self.canvas.place(*args, **kwargs) self.canvas.place(*args, **kwargs)
def _draw(self): def _draw(self, _use_self_text=None):
self._draw_corner(0, 0, 0, 0) self._draw_corner(0, 0, 0, 0)
self._draw_corner(1, 0, self.w-4, 0) self._draw_corner(1, 0, self.w-4, 0)
self._draw_corner(0, 1, 0, self.h-5) self._draw_corner(0, 1, 0, self.h-5)
@ -173,6 +173,7 @@ class Button:
self._fill_obj.append(self.canvas.create_rectangle( self._fill_obj.append(self.canvas.create_rectangle(
5, 2, self.w-4, self.h-2, width=0, fill=self.color[self._color_fg2])) 5, 2, self.w-4, self.h-2, width=0, fill=self.color[self._color_fg2]))
if (_use_self_text is None):
if (self._color_text is None): if (self._color_text is None):
self._fill_fc.append(self.color[self._color_fg]) self._fill_fc.append(self.color[self._color_fg])
self._fill_gc.append(self.color["regular_text"]) self._fill_gc.append(self.color["regular_text"])

View File

@ -1,8 +1,5 @@
import tkinter import tkinter
from tkinter import ttk from tkinter import ttk
try:
import color_tmpl
except ImportError:
from magictk import color_tmpl from magictk import color_tmpl

View File

@ -3,107 +3,28 @@ import tkinter
import sys import sys
from tkinter import ttk from tkinter import ttk
from tkinter import font as tkfont from tkinter import font as tkfont
try:
import color_tmpl
except ImportError:
from magictk import color_tmpl from magictk import color_tmpl
try:
import photoload
except ImportError:
from magictk import photoload from magictk import photoload
try:
import submenu
except ImportError:
from magictk import submenu from magictk import submenu
from magictk import fontconfig
from magictk import button
def set_font(): class Select(button.Button):
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 Select:
color = color_tmpl.default_color color = color_tmpl.default_color
__fill_obj = [] _fill_obj = []
__fill_func = [] _fill_func = []
__fill_gc = [] _fill_gc = []
__fill_fc = [] _fill_fc = []
__fill_hc = [] _fill_hc = []
hover_mode = 0.0 hover_mode = 0.0
__is_hover = 0 _is_hover = 0
__flash_t = 0 _flash_t = 0
max_flash = 6 max_flash = 6
__anim_obj_id = -1 _anim_obj_id = -1
__color_bd = "border_base"
__color_bg = "background"
__color_fg = "primary"
__color_fg1 = "primary"
__color_fg2 = "background"
text = "Select"
def __draw_corner(self, r_x, r_y, x, y, **kwargs): def _draw_arrow(self, x, y, **kwargs):
border_info = json.loads(photoload.loadres("buttonborder"))
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
g_color = color_tmpl.mix_color(
self.color["background"], self.color[self.__color_bd], int((1-lcolor/255)*1000)/1000)
if (j < 0):
f_color = color_tmpl.mix_color(
self.color[self.__color_fg2], self.color[self.__color_fg1], int((1-lcolor/255)*1000)/1000)
else:
f_color = color_tmpl.mix_color(
self.color["background"], self.color[self.__color_fg1], int((1-lcolor/255)*1000)/1000)
if (j < 0):
h_color = color_tmpl.mix_color(
self.color[self.__color_fg2], self.color[self.__color_fg], int((1-lcolor/255)*1000)/1000)
else:
h_color = color_tmpl.mix_color(
self.color["background"], self.color[self.__color_fg], int((1-lcolor/255)*1000)/1000)
obj = self.canvas.create_rectangle(
px, py, px, py, width=0, fill=g_color)
def update_color(obj, g_color, f_color, h_color):
if (self.__is_hover == 2):
self.canvas.itemconfig(
obj, fill=h_color)
else:
self.canvas.itemconfig(
obj, fill=color_tmpl.mix_color(g_color, f_color, self.hover_mode))
self.__fill_func.append(update_color)
self.__fill_gc.append(g_color)
self.__fill_fc.append(f_color)
self.__fill_hc.append(h_color)
self.__fill_obj.append(obj)
x_n += 1
y_n += 1
def __draw_arrow(self, x, y, **kwargs):
border_info = self.__arrow_json[0] border_info = self.__arrow_json[0]
self.__arrow_list = [] self.__arrow_list = []
y_n = 0 y_n = 0
@ -115,7 +36,7 @@ class Select:
py = y+y_n+1 py = y+y_n+1
lcolor = j lcolor = j
g_color = color_tmpl.mix_color( g_color = color_tmpl.mix_color(
self.color["background"], self.color[self.__color_bd], int((1-lcolor/255)*1000)/1000) self.color["background"], self.color[self._color_bd], int((1-lcolor/255)*1000)/1000)
obj = self.canvas.create_rectangle( obj = self.canvas.create_rectangle(
px, py, px, py, width=0, fill=g_color) px, py, px, py, width=0, fill=g_color)
@ -124,150 +45,81 @@ class Select:
x_n += 1 x_n += 1
y_n += 1 y_n += 1
def __update_color(self):
n = 0
for i in self.__fill_func:
i(self.__fill_obj[n], self.__fill_gc[n],
self.__fill_fc[n], self.__fill_hc[n])
n += 1
def __init__(self, master=None, root_anim=None, w=200, h=30, text="Select", color_list: None | dict = None, items=[]): def __init__(self, master=None, root_anim=None, w=200, h=30, text="Select", color_list: None | dict = None, items=[]):
set_font() global use_font
use_font = fontconfig.getfont()
self.__arrow_json = json.loads(photoload.loadres("selectarrow")) self.__arrow_json = json.loads(photoload.loadres("selectarrow"))
self.items = items self.items = items
self.w = max(120, w) self._color_bd = "border_base"
self.h = max(30, h) self._color_bg = "background"
self.text = text self._color_bg1 = "background"
self.choose = -1 self._color_fg = "primary"
self.__master = master self._color_fg1 = "primary"
if (color_list is not None): self._color_fg2 = "background"
self.color = color_list self._color_fg3 = "background"
if (root_anim == None): self._color_text = None
self.root = master.root super().__init__(master=master, root_anim=root_anim, w=w,
else: h=h, text=text, color_list=color_list, _set_defaultcolor=True)
self.root = root_anim
self.canvas = tkinter.Canvas(
master, bg=self.color["background"], width=self.w, height=self.h, borderwidth=0, bd=0, highlightcolor=self.color["background"], highlightthickness=0)
self.__draw()
self.__update_color()
self.__bind_event()
self.bind_anim()
self.__menuobj = submenu.MenuObjs() self.__menuobj = submenu.MenuObjs()
self.__last = 0 self.__last = 0
for i in self.items: for i in self.items:
self.__menuobj.addmenu(i, self.__callback_menu) self.__menuobj.addmenu(i, self._callback_menu)
def pack(self, *args, **kwargs): def _draw(self):
self.canvas.pack(*args, **kwargs) super()._draw(True)
def guid(self, *args, **kwargs):
self.canvas.guid(*args, **kwargs)
def place(self, *args, **kwargs):
self.canvas.place(*args, **kwargs)
def __draw(self):
self.__draw_corner(0, 0, 0, 0)
self.__draw_corner(1, 0, self.w-4, 0)
self.__draw_corner(0, 1, 0, self.h-5)
self.__draw_corner(1, 1, self.w-4, self.h-5)
def update_color(obj, g_color, f_color, h_color): def update_color(obj, g_color, f_color, h_color):
if (self.__is_hover == 2): if (self._is_hover == 2):
self.canvas.itemconfig( self.canvas.itemconfig(
obj, fill=h_color) obj, fill=h_color)
else: else:
self.canvas.itemconfig( self.canvas.itemconfig(
obj, fill=color_tmpl.mix_color(g_color, f_color, self.hover_mode)) obj, fill=color_tmpl.mix_color(g_color, f_color, self.hover_mode))
self.__fill_fc.append(self.color[self.__color_fg1])
self.__fill_gc.append(self.color[self.__color_bd])
self.__fill_hc.append(self.color[self.__color_fg])
self.__fill_func.append(update_color)
self.__fill_obj.append(self.canvas.create_line(
1, 5, 1, self.h-5, width=1, fill=self.color[self.__color_bd]))
self.__fill_fc.append(self.color[self.__color_fg1])
self.__fill_gc.append(self.color[self.__color_bd])
self.__fill_hc.append(self.color[self.__color_fg])
self.__fill_func.append(update_color)
self.__fill_obj.append(self.canvas.create_line(
5, 1, self.w-4, 1, width=1, fill=self.color[self.__color_fg1]))
self.__fill_fc.append(self.color[self.__color_fg1])
self.__fill_gc.append(self.color[self.__color_bd])
self.__fill_hc.append(self.color[self.__color_fg])
self.__fill_func.append(update_color)
self.__fill_obj.append(self.canvas.create_line(
self.w-1, 5, self.w-1, self.h-5, width=1, fill=self.color[self.__color_fg1]))
self.__fill_fc.append(self.color[self.__color_fg1])
self.__fill_gc.append(self.color[self.__color_bd])
self.__fill_hc.append(self.color[self.__color_fg])
self.__fill_func.append(update_color)
self.__fill_obj.append(self.canvas.create_line(
5, self.h-2, self.w-4, self.h-2, width=1, fill=self.color[self.__color_fg1]))
self.__fill_fc.append(self.color[self.__color_fg2])
self.__fill_gc.append(self.color["background"])
self.__fill_hc.append(self.color[self.__color_fg2])
self.__fill_func.append(update_color)
self.__fill_obj.append(self.canvas.create_rectangle(
2, 5, self.w-1, self.h-5, width=0, fill=self.color[self.__color_fg2]))
self.__fill_fc.append(self.color[self.__color_fg2])
self.__fill_gc.append(self.color["background"])
self.__fill_hc.append(self.color[self.__color_fg2])
self.__fill_func.append(update_color)
self.__fill_obj.append(self.canvas.create_rectangle(
5, 2, self.w-4, self.h-2, width=0, fill=self.color[self.__color_fg2]))
self.__text_obj = self.canvas.create_text( self.__text_obj = self.canvas.create_text(
20, int(self.h/2), text=self.text, font=(use_font, 10), justify="left") 20, int(self.h/2), text=self.text, font=(use_font, 10), justify="left")
self.__fill_fc.append(self.color["placeholder"]) self._fill_fc.append(self.color["placeholder"])
self.__fill_gc.append(self.color["regular_text"]) self._fill_gc.append(self.color["regular_text"])
self.__fill_hc.append(self.color["placeholder"]) self._fill_hc.append(self.color["placeholder"])
self.__fill_func.append(update_color) self._fill_func.append(update_color)
self.__fill_obj.append(self.__text_obj) self._fill_obj.append(self.__text_obj)
self.canvas.moveto(self.__text_obj, 16, self.h//2-10) self.canvas.moveto(self.__text_obj, 16, self.h//2-10)
self._draw_arrow(self.w-30, (self.h-12)//2)
self.__draw_arrow(self.w-30, (self.h-12)//2)
def bind_anim(self): def bind_anim(self):
def update_arrow(): def update_arrow():
datas = self.__arrow_json[self.__flash_t] datas = self.__arrow_json[self._flash_t]
y_n = 0 y_n = 0
for i in datas: for i in datas:
x_n = 0 x_n = 0
for j in i: for j in i:
self.canvas.itemconfigure(self.__arrow_list[y_n][x_n], fill=(color_tmpl.mix_color( self.canvas.itemconfigure(self.__arrow_list[y_n][x_n], fill=(color_tmpl.mix_color(
self.color["background"], self.color[self.__color_bd], int((1-j/255)*1000)/1000))) self.color["background"], self.color[self._color_bd], int((1-j/255)*1000)/1000)))
x_n += 1 x_n += 1
y_n += 1 y_n += 1
def anim_magictk(): def anim_magictk():
if (self.__is_hover == 1 and self.__flash_t < self.max_flash): if (self._is_hover == 1 and self._flash_t < self.max_flash):
self.__flash_t += (1 if (len(self.root.anim) > 6) else 1) self._flash_t += (1 if (len(self.root.anim) > 6) else 1)
self.__flash_t = min(self.__flash_t, self.max_flash) self._flash_t = min(self._flash_t, self.max_flash)
self.hover_mode = self.__flash_t/self.max_flash self.hover_mode = self._flash_t/self.max_flash
self.__update_color() self._update_color()
elif (self.__is_hover == 0 and self.__flash_t > 0): elif (self._is_hover == 0 and self._flash_t > 0):
self.__flash_t -= (1 if (len(self.root.anim) > 6) else 1) self._flash_t -= (1 if (len(self.root.anim) > 6) else 1)
self.__flash_t = max(self.__flash_t, 0) self._flash_t = max(self._flash_t, 0)
self.hover_mode = self.__flash_t/self.max_flash self.hover_mode = self._flash_t/self.max_flash
self.__update_color() self._update_color()
elif (self._is_hover == 0 and self._flash_t == 0):
return -1
update_arrow() update_arrow()
# elif (self.__is_hover == 0 and self.__flash_t <= 0):
# if self.__anim_obj_id != -1:
# self.__anim_obj_id = None
def anim_normal(*args): def anim_normal(*args):
if (self.__is_hover == 1 and self.__flash_t < self.max_flash): if (self._is_hover == 1 and self._flash_t < self.max_flash):
self.__flash_t += 1 self._flash_t += 1
self.hover_mode = self.__flash_t/self.max_flash self.hover_mode = self._flash_t/self.max_flash
self.__update_color() self.__update_color()
elif (self.__is_hover == 0 and self.__flash_t > 0): elif (self._is_hover == 0 and self._flash_t > 0):
self.__flash_t -= 1 self._flash_t -= 1
self.hover_mode = self.__flash_t/self.max_flash self.hover_mode = self._flash_t/self.max_flash
self.__update_color() self.__update_color()
self.root.after(anim_normal, 16) self.root.after(anim_normal, 16)
update_arrow() update_arrow()
@ -281,7 +133,7 @@ class Select:
self.root.anim.append(anim_magictk) self.root.anim.append(anim_magictk)
self.__anim_obj_id = self.root.anim[-1] self.__anim_obj_id = self.root.anim[-1]
def __callback_menu(self, obj, ids): def _callback_menu(self, obj, ids):
self.__menuobj.menu_effect[self.__last] = {} self.__menuobj.menu_effect[self.__last] = {}
self.__menuobj.menu_effect[ids] = { self.__menuobj.menu_effect[ids] = {
"fill": self.color["primary"], "font": (obj.font[0], obj.font[1], "bold")} "fill": self.color["primary"], "font": (obj.font[0], obj.font[1], "bold")}
@ -289,15 +141,16 @@ class Select:
self.canvas.itemconfigure(self.__text_obj, text=self.items[ids]) self.canvas.itemconfigure(self.__text_obj, text=self.items[ids])
self.canvas.moveto(self.__text_obj, 16, self.h//2-10) self.canvas.moveto(self.__text_obj, 16, self.h//2-10)
def __bind_event(self): def _bind_event(self):
def closecallback(obj): def closecallback(obj):
self.__is_hover = 0 self._is_hover = 0
def pressrelease_v(event): def pressrelease_v(event):
if (self.__is_hover == 1): self.bind_anim()
if (self._is_hover == 1):
self.menus.close() self.menus.close()
else: else:
self.__is_hover = 1 self._is_hover = 1
self.menus = submenu.Menu( self.menus = submenu.Menu(
x=event.x_root-event.x, x=event.x_root-event.x,
y=event.y_root-event.y+self.h+4, y=event.y_root-event.y+self.h+4,
@ -305,5 +158,5 @@ class Select:
h=min(8*34, len(self.items)*34+12+4), h=min(8*34, len(self.items)*34+12+4),
root=self.root, menuobj=self.__menuobj, closecallback=closecallback root=self.root, menuobj=self.__menuobj, closecallback=closecallback
) )
self.__update_color() self._update_color()
self.canvas.bind("<ButtonRelease-1>", pressrelease_v) self.canvas.bind("<ButtonRelease-1>", pressrelease_v)