style(HDMI-Tool): 按用户标记微调 CTk 界面
This commit is contained in:
+66
-26
@@ -111,8 +111,8 @@ class App(ctk.CTk):
|
||||
ctk.set_appearance_mode(mode)
|
||||
self._apply_tv_colors()
|
||||
|
||||
def _card(self, parent, title, button=None, command=None):
|
||||
"""卡片容器: 圆角边框 + 标题行(可带右侧小按钮), 返回 (卡片, 内容 frame)
|
||||
def _card(self, parent, title, button=None, command=None, right_label=None):
|
||||
"""卡片容器: 圆角边框 + 标题行(可带右侧小按钮/右对齐标签), 返回 (卡片, 内容 frame)
|
||||
|
||||
卡片自身用 grid 参与列布局; 卡片内部(head/content/行控件)一律用 pack。
|
||||
"""
|
||||
@@ -121,6 +121,9 @@ class App(ctk.CTk):
|
||||
head = ctk.CTkFrame(card, fg_color='transparent')
|
||||
head.pack(fill='x', padx=12, pady=(8, 0))
|
||||
ctk.CTkLabel(head, text=title, font=BOLD, anchor='w').pack(side='left')
|
||||
if right_label is not None:
|
||||
ctk.CTkLabel(head, textvariable=right_label,
|
||||
text_color='gray60').pack(side='right')
|
||||
if button:
|
||||
ctk.CTkButton(head, text=button, width=92, height=24,
|
||||
command=command).pack(side='right')
|
||||
@@ -141,8 +144,8 @@ class App(ctk.CTk):
|
||||
|
||||
body = ctk.CTkFrame(self, fg_color='transparent')
|
||||
body.pack(fill='both', expand=True, padx=12, pady=(4, 12))
|
||||
body.grid_columnconfigure(0, weight=11, uniform='col')
|
||||
body.grid_columnconfigure(1, weight=9, uniform='col')
|
||||
body.grid_columnconfigure(0, weight=1, uniform='col')
|
||||
body.grid_columnconfigure(1, weight=1, uniform='col')
|
||||
body.grid_rowconfigure(0, weight=1)
|
||||
left = ctk.CTkFrame(body, fg_color='transparent')
|
||||
left.grid(row=0, column=0, sticky='nsew')
|
||||
@@ -160,24 +163,22 @@ class App(ctk.CTk):
|
||||
).pack(expand=True)
|
||||
|
||||
def _build_left(self, col):
|
||||
col.grid_rowconfigure(1, weight=2) # 支持的模式
|
||||
col.grid_rowconfigure(2, weight=3) # EDID 信息
|
||||
col.grid_rowconfigure(1, weight=3) # 支持的模式
|
||||
col.grid_rowconfigure(2, weight=2) # EDID 信息
|
||||
col.grid_rowconfigure(4, weight=1) # EDID 原始数据
|
||||
col.grid_columnconfigure(0, weight=1)
|
||||
|
||||
# -- 显示器选择区域 --
|
||||
card, c = self._card(col,'显示器选择区域')
|
||||
self.lbl_cur_var = tk.StringVar(value='当前输出: —')
|
||||
card, c = self._card(col, '显示器选择区域', right_label=self.lbl_cur_var)
|
||||
card.grid(row=0, column=0, sticky='ew')
|
||||
row = ctk.CTkFrame(c, fg_color='transparent')
|
||||
row.pack(fill='x')
|
||||
self.cbo = ctk.CTkComboBox(row, width=380, state='readonly',
|
||||
self.cbo = ctk.CTkComboBox(row, state='readonly',
|
||||
command=lambda _=None: self._on_select())
|
||||
self.cbo.pack(side='left')
|
||||
self.cbo.pack(side='left', fill='x', expand=True)
|
||||
ctk.CTkButton(row, text='刷新', width=64,
|
||||
command=self._load_displays).pack(side='left', padx=(6, 0))
|
||||
self.lbl_cur = ctk.CTkLabel(c, text='当前输出: —', anchor='w',
|
||||
text_color='gray60')
|
||||
self.lbl_cur.pack(fill='x', pady=(6, 0))
|
||||
|
||||
# -- 支持的模式 --
|
||||
card, c = self._card(col,'支持的模式 (EDID 解算)')
|
||||
@@ -193,7 +194,7 @@ class App(ctk.CTk):
|
||||
command=self._restore_mode).pack(side='left', padx=(6, 0))
|
||||
ctk.CTkLabel(row, text='临时切换, 重启还原',
|
||||
text_color='gray50').pack(side='left', padx=8)
|
||||
self.txt_modes = ctk.CTkTextbox(c, font=MONO, height=100)
|
||||
self.txt_modes = ctk.CTkTextbox(c, font=MONO, height=150)
|
||||
self.txt_modes.pack(fill='both', expand=True, pady=(8, 0))
|
||||
self.txt_modes.configure(state='disabled')
|
||||
|
||||
@@ -245,11 +246,12 @@ class App(ctk.CTk):
|
||||
btn = ctk.CTkButton(cell, text=self.slots[i]['name'], width=96,
|
||||
command=lambda i=i: self._show_custom(i))
|
||||
btn.pack(side='left')
|
||||
ctk.CTkButton(cell, text='⚙', width=30, height=24,
|
||||
ctk.CTkButton(cell, text='\uE713', width=30, height=24,
|
||||
font=('Segoe MDL2 Assets', 13),
|
||||
command=lambda i=i: self._configure_slot(i)
|
||||
).pack(side='left', padx=(4, 0))
|
||||
self.slot_buttons.append(btn)
|
||||
ctk.CTkLabel(row3, text='点击投图, ⚙ 配置图片',
|
||||
ctk.CTkLabel(row3, text='点击投图, 齿轮按钮配置图片',
|
||||
text_color='gray50').pack(side='left', padx=4)
|
||||
|
||||
# -- EDID 原始数据 --
|
||||
@@ -338,23 +340,31 @@ class App(ctk.CTk):
|
||||
rowa = ctk.CTkFrame(c, fg_color='transparent')
|
||||
rowa.pack(fill='x')
|
||||
ctk.CTkLabel(rowa, text='光强(54-800):').pack(side='left')
|
||||
self.var_light = tk.IntVar(value=100)
|
||||
self.var_light = tk.StringVar(value='100')
|
||||
sld = ctk.CTkSlider(rowa, from_=54, to=800, number_of_steps=149,
|
||||
command=lambda v: self.var_light.set(int(round(float(v)))))
|
||||
command=lambda v: self.var_light.set(str(int(round(float(v))))))
|
||||
sld.set(100)
|
||||
sld.pack(side='left', fill='x', expand=True, padx=8)
|
||||
ctk.CTkLabel(rowa, textvariable=self.var_light, width=40).pack(side='left')
|
||||
self.sld_light = sld
|
||||
self.ent_light = ctk.CTkEntry(rowa, width=56, justify='center',
|
||||
textvariable=self.var_light)
|
||||
self.ent_light.pack(side='left')
|
||||
self.ent_light.bind('<Return>', self._light_entry_apply)
|
||||
ctk.CTkButton(rowa, text='下发 M731S', width=110,
|
||||
command=self._dlpc_send_light).pack(side='left', padx=(6, 0))
|
||||
rowb = ctk.CTkFrame(c, fg_color='transparent')
|
||||
rowb.pack(fill='x', pady=(8, 0))
|
||||
ctk.CTkLabel(rowb, text='定时投光(秒):').pack(side='left')
|
||||
self.var_timer = tk.IntVar(value=2)
|
||||
self.var_timer = tk.StringVar(value='2')
|
||||
sld_t = ctk.CTkSlider(rowb, from_=0, to=32, number_of_steps=32,
|
||||
command=lambda v: self.var_timer.set(int(round(float(v)))))
|
||||
command=lambda v: self.var_timer.set(str(int(round(float(v))))))
|
||||
sld_t.set(2)
|
||||
sld_t.pack(side='left', fill='x', expand=True, padx=8)
|
||||
ctk.CTkLabel(rowb, textvariable=self.var_timer, width=40).pack(side='left')
|
||||
self.sld_timer = sld_t
|
||||
self.ent_timer = ctk.CTkEntry(rowb, width=56, justify='center',
|
||||
textvariable=self.var_timer)
|
||||
self.ent_timer.pack(side='left')
|
||||
self.ent_timer.bind('<Return>', self._timer_entry_apply)
|
||||
ctk.CTkButton(rowb, text='开光机(定时)', width=110,
|
||||
command=self._dlpc_send_timer).pack(side='left', padx=(6, 0))
|
||||
|
||||
@@ -384,7 +394,7 @@ class App(ctk.CTk):
|
||||
self.cbo.configure(values=self._disp_labels)
|
||||
if not self.displays:
|
||||
self._cur_label = ''
|
||||
self.lbl_cur.configure(text='未找到活动显示器')
|
||||
self.lbl_cur_var.set('未找到活动显示器')
|
||||
return
|
||||
idx = self._disp_labels.index(prev) if prev in self._disp_labels else 0
|
||||
self._cur_label = self._disp_labels[idx]
|
||||
@@ -396,7 +406,7 @@ class App(ctk.CTk):
|
||||
return
|
||||
self._cur_label = self.cbo.get()
|
||||
d = self._cur_display()
|
||||
self.lbl_cur.configure(text=f"当前输出: {d['cur_mode']}")
|
||||
self.lbl_cur_var.set(f"当前输出: {d['cur_mode']}")
|
||||
keys, modes = display_win.enum_modes(d['device'])
|
||||
self._modes = modes
|
||||
self.cbo_mode.configure(values=keys)
|
||||
@@ -474,7 +484,7 @@ class App(ctk.CTk):
|
||||
def _show_custom(self, idx):
|
||||
slot = self.slots[idx]
|
||||
if not slot['file']:
|
||||
messagebox.showinfo('未配置图片', f'请先点击"⚙"为"{slot["name"]}"配置图片。')
|
||||
messagebox.showinfo('未配置图片', f'请先点击齿轮按钮为"{slot["name"]}"配置图片。')
|
||||
return
|
||||
path = os.path.join(config.BASE_DIR, slot['file'])
|
||||
if not os.path.exists(path):
|
||||
@@ -671,15 +681,45 @@ class App(ctk.CTk):
|
||||
if cmd:
|
||||
self._dlpc_send(cmd)
|
||||
|
||||
def _light_entry_apply(self, _evt=None):
|
||||
"""滑条数值输入框回车: 校验并限幅 54-800, 同步回滑条"""
|
||||
try:
|
||||
v = int(self.var_light.get())
|
||||
except ValueError:
|
||||
self.var_light.set(str(int(float(self.sld_light.get()))))
|
||||
return
|
||||
v = max(54, min(800, v))
|
||||
self.sld_light.set(v)
|
||||
self.var_light.set(str(v))
|
||||
|
||||
def _timer_entry_apply(self, _evt=None):
|
||||
"""定时滑条数值输入框回车: 校验并限幅 0-32, 同步回滑条"""
|
||||
try:
|
||||
v = int(self.var_timer.get())
|
||||
except ValueError:
|
||||
self.var_timer.set(str(int(float(self.sld_timer.get()))))
|
||||
return
|
||||
v = max(0, min(32, v))
|
||||
self.sld_timer.set(v)
|
||||
self.var_timer.set(str(v))
|
||||
|
||||
def _dlpc_send_light(self):
|
||||
v = int(self.var_light.get())
|
||||
try:
|
||||
v = int(self.var_light.get())
|
||||
except ValueError:
|
||||
messagebox.showinfo('光强非法', '光强需为 54-800 的整数')
|
||||
return
|
||||
if not 54 <= v <= 800:
|
||||
messagebox.showinfo('光强越界', '光强范围 54-800(越界固件会回 err:OL)')
|
||||
return
|
||||
self._dlpc_send(f'M731S{v}')
|
||||
|
||||
def _dlpc_send_timer(self):
|
||||
v = int(self.var_timer.get())
|
||||
try:
|
||||
v = int(self.var_timer.get())
|
||||
except ValueError:
|
||||
messagebox.showinfo('定时非法', '定时投光需为 0-32 的整数秒')
|
||||
return
|
||||
self._dlpc_send('M730S0' if v <= 0 else f'M730S0T{v * 1000}')
|
||||
|
||||
def destroy(self):
|
||||
|
||||
Reference in New Issue
Block a user