22import tkinter as tk
33from tkinter import filedialog , messagebox , ttk
44from typing import List , Optional
5+ import threading
6+ import time
7+ from collections import deque
58
69from src .player import Player
710from src .event import Event
811
912
1013class BaseApp :
11- def __init__ (self , root : tk .Tk , title : str ):
14+ def __init__ (self , root : tk .Tk , title : str , create_key_display : bool = True ):
1215 self .root = root
1316 self .root .title (title )
1417 self .score_text : Optional [str ] = None
@@ -21,6 +24,18 @@ def __init__(self, root: tk.Tk, title: str):
2124 self ._create_params_frame ()
2225 self ._create_control_frame ()
2326 self ._create_tips_frame ()
27+
28+ # 根据参数决定是否创建按键显示框架
29+ if create_key_display :
30+ self ._create_key_display_frame ()
31+
32+ # 初始化按键显示相关变量
33+ self .keys = deque (maxlen = 14 ) # 显示最近maxlen个按键
34+ self .last_press_time = {}
35+ self .running = True
36+
37+ # 启动按键监听
38+ self ._start_key_listener ()
2439
2540 def _create_file_bar (self ):
2641 file_bar = tk .Frame (self .frm )
@@ -89,6 +104,85 @@ def _create_tips_frame(self):
89104 "4) 如无响应尝试以管理员身份运行。"
90105 )).pack (fill = "x" )
91106
107+ def _create_key_display_frame (self ):
108+ """创建按键显示框架"""
109+ key_frame = tk .LabelFrame (self .frm , text = "按键显示" )
110+ key_frame .pack (fill = "x" , pady = 8 )
111+
112+ # 创建按键显示标签
113+ self .lbl_keys = tk .Label (
114+ key_frame ,
115+ text = "等待按键..." ,
116+ font = ("Consolas" , 16 , "bold" ),
117+ fg = "white" ,
118+ bg = "#C0C0C0" , # 使用深灰色模拟半透明效果
119+ height = 2 ,
120+ anchor = "center" ,
121+ relief = "flat" , # 去掉边框,让背景更平滑
122+ borderwidth = 0
123+ )
124+ self .lbl_keys .pack (fill = "x" , padx = 4 , pady = 4 )
125+
126+ # 添加说明文字
127+ tk .Label (key_frame , text = "实时显示当前按下的按键" , font = ("微软雅黑" , 9 ), fg = "gray" ).pack (anchor = "w" , padx = 4 )
128+
129+ def _start_key_listener (self ):
130+ """启动按键监听线程"""
131+ try :
132+ from pynput import keyboard
133+
134+ def on_press (key ):
135+ """键盘按下事件"""
136+ try :
137+ k = key .char .upper ()
138+ except AttributeError :
139+ k = str (key ).replace ("Key." , "" ).upper ()
140+
141+ self .keys .append (k )
142+ self .last_press_time [k ] = time .time ()
143+ self ._update_key_display ()
144+
145+ # 启动键盘监听器
146+ self .key_listener = keyboard .Listener (on_press = on_press )
147+ self .key_listener .start ()
148+
149+ # 启动清理过期按键的线程
150+ threading .Thread (target = self ._cleanup_keys_loop , daemon = True ).start ()
151+
152+ except ImportError :
153+ # 如果没有安装pynput,显示提示信息
154+ self .lbl_keys .config (
155+ text = "需要安装 pynput 模块\n pip install pynput" ,
156+ font = ("微软雅黑" , 10 ),
157+ fg = "red" ,
158+ bg = "lightgray"
159+ )
160+
161+ def _update_key_display (self ):
162+ """更新按键显示"""
163+ if hasattr (self , 'lbl_keys' ):
164+ if self .keys :
165+ display_text = " " .join (self .keys )
166+ self .lbl_keys .config (text = display_text )
167+ else :
168+ self .lbl_keys .config (text = "等待按键..." )
169+
170+ def _cleanup_keys_loop (self ):
171+ """后台循环,清理过期按键"""
172+ while self .running :
173+ now = time .time ()
174+ removed = False
175+ for k in list (self .keys ):
176+ if now - self .last_press_time .get (k , 0 ) > 2.0 : # 2秒后自动清除
177+ try :
178+ self .keys .remove (k )
179+ removed = True
180+ except ValueError :
181+ pass
182+ if removed :
183+ self ._update_key_display ()
184+ time .sleep (0.2 )
185+
92186 def update_progress (self , current : int , total : int ):
93187 """更新进度条和进度标签"""
94188 if total > 0 :
@@ -207,6 +301,15 @@ def toggle_play_pause(self):
207301 except Exception :
208302 pass
209303
304+ def __del__ (self ):
305+ """析构函数,清理资源"""
306+ self .running = False
307+ if hasattr (self , 'key_listener' ):
308+ try :
309+ self .key_listener .stop ()
310+ except :
311+ pass
312+
210313
211314if __name__ == '__main__' :
212315 pass
0 commit comments