fix(menu): duplicate event binding & position when using keyboard

Signed-off-by: 晨叶梦春 <wuziqian211@126.com>
This commit is contained in:
晨叶梦春
2026-08-05 15:44:34 +08:00
parent 1e73902560
commit e51c9f9f3d
2 changed files with 43 additions and 12 deletions
+14 -6
View File
@@ -36,12 +36,20 @@ def parse_and_copy() -> None: # 解析并复制链接
messagebox.showwarning("警告", "以下 “行” 无法解析:\n" + "\n".join(failed_urls))
if resource_urls:
url_text.clipboard_clear()
url_text.clipboard_append("\n".join(resource_urls)) # 将链接复制到剪贴板
messagebox.showinfo(
"提示",
f'资源链接已复制到剪贴板。\n注意:链接可能无法直接下载,需要加上以下 HTTP 标头才能下载{"(以下标头含有隐私信息,请勿分享给别人)" if config.access_token else ""}:\n\nAuthorization: Bearer {config.access_token or "0"}\nX-ND-AUTH: MAC id="{config.access_token or "0"}",nonce="0",mac="0"'
)
try:
resource_urls_str = "\n".join(resource_urls)
url_text.clipboard_clear()
url_text.clipboard_append(resource_urls_str) # 将链接复制到剪贴板
if url_text.clipboard_get() == resource_urls_str: # 检查剪贴板内容是否正确
messagebox.showinfo(
"提示",
f'资源链接已复制到剪贴板。\n注意:链接可能无法直接下载,需要加上以下 HTTP 标头才能下载{"(以下标头含有隐私信息,请勿分享给别人)" if config.access_token else ""}:\n\nAuthorization: Bearer {config.access_token or "0"}\nX-ND-AUTH: MAC id="{config.access_token or "0"}",nonce="0",mac="0"'
)
else:
messagebox.showerror("错误", "无法将链接复制到剪贴板,请手动复制。")
except Exception as e:
print_error(e)
messagebox.showerror("错误", "无法将链接复制到剪贴板,请手动复制。")
def download() -> None: # 下载资源文件
global download_states
+29 -6
View File
@@ -9,9 +9,12 @@ from . import runtime
from .theme import register_themed_widget
from ..platform_utils import os_name
root_handlers_bound: dict[tk.Menu, bool] = {} # 用于记录每个右键菜单是否已绑定根窗口事件,避免重复绑定
def bind_context_menu(parent: tk.Widget, type: Literal["normal", "noundo", "readonly"] = "normal") -> None: # 创建右键菜单
context_menu = tk.Menu(parent, tearoff=False, font="AppBodyFont")
register_themed_widget(context_menu)
root_handlers_bound[context_menu] = False # 初始化为未绑定根窗口事件
if type == "normal":
context_menu.add_command(label="撤销 (U)", underline=4, accelerator="Ctrl+Z", command=lambda: parent.event_generate("<<Undo>>"))
context_menu.add_separator()
@@ -23,17 +26,37 @@ def bind_context_menu(parent: tk.Widget, type: Literal["normal", "noundo", "read
context_menu.add_separator()
context_menu.add_command(label="全选 (A)", underline=4, accelerator="Ctrl+A", command=lambda: parent.event_generate("<<SelectAll>>"))
def show_context_menu(event: tk.Event) -> None:
context_menu.post(event.x_root, event.y_root)
def show_context_menu(event: tk.Event, keyboard: bool = False) -> None:
if not keyboard and event.x_root >= 0 and event.y_root >= 0:
context_menu.post(event.x_root, event.y_root)
else: # 通过键盘打开菜单或 x_root 与 y_root 无效时
try: # 优先尝试在插入点(文本控件)位置显示菜单
bbox = parent.bbox("insert") # 此处可能抛异常或返回 None
if bbox:
bx, by, bw, bh = bbox
x_root = parent.winfo_rootx() + bx
y_root = parent.winfo_rooty() + by + bh
else:
raise Exception("无法获取插入点位置")
except Exception: # 再尝试使用鼠标指针位置(如果有)
px, py = parent.winfo_pointerx(), parent.winfo_pointery()
if px >= 0 and py >= 0:
x_root, y_root = px, py
else: # 最后回退到控件中心
x_root = round(parent.winfo_rootx() + parent.winfo_width() // 2)
y_root = round(parent.winfo_rooty() + parent.winfo_height() // 2)
context_menu.post(x_root, y_root)
context_menu.bind("<FocusOut>", lambda e: context_menu.unpost()) # 绑定失焦事件,失焦时自动关闭菜单
context_menu.bind("<Escape>", lambda e: context_menu.unpost(), add="+") # 绑定 Esc 键,按下时关闭菜单
runtime.root.bind("<Escape>", lambda e: context_menu.unpost(), add="+") # 绑定 Esc 键,按下时关闭菜单
runtime.root.bind("<Button-1>", lambda e: context_menu.unpost(), add="+") # 绑定左键点击事件,点击其他地方也关闭菜单
if not root_handlers_bound.get(context_menu):
root_handlers_bound[context_menu] = True
runtime.root.bind("<Escape>", lambda e: context_menu.unpost(), add="+") # 绑定 Esc 键,按下时关闭菜单
runtime.root.bind("<Button-1>", lambda e: context_menu.unpost(), add="+") # 绑定左键点击事件,点击其他地方也关闭菜单
# 绑定右键菜单到文本框
parent.bind("<Button-3>", show_context_menu) # 鼠标右键
parent.bind("<Menu>", show_context_menu) # BUG: 按下菜单键不起作用
parent.bind("<Shift-F10>", show_context_menu)
parent.bind("<Menu>", lambda e: show_context_menu(e, True)) # BUG: 按下菜单键不起作用
parent.bind("<Shift-F10>", lambda e: show_context_menu(e, True))
if os_name == "Darwin":
parent.bind("<Control-Button-1>", show_context_menu) # Command + 鼠标左键
parent.bind("<Button-2>", show_context_menu) # 鼠标中键