continue fixing....

This commit is contained in:
2026-08-12 13:16:40 +08:00
parent c7219a2555
commit b3c264e910
2 changed files with 89 additions and 7 deletions

View File

@@ -69,7 +69,7 @@ pip install -r requirements.txt
| `←` / `→` | 后退 / 前进 10 秒 | | `←` / `→` | 后退 / 前进 10 秒 |
| `Shift+←` / `Shift+→` | 后退 / 前进 60 秒 | | `Shift+←` / `Shift+→` | 后退 / 前进 60 秒 |
| `↑` / `↓` | 音量 +5 / -5 | | `↑` / `↓` | 音量 +5 / -5 |
| `Ctrl+↑` / `Ctrl+↓` | 快进步长 +5 / -5macOS 亦支持 `Command+↑ / ↓` | | `Ctrl+↑` / `Ctrl+↓` | 快进步长 +1 / -1macOS 亦支持 `Command+↑ / ↓` |
| `M` | 静音 / 恢复 | | `M` | 静音 / 恢复 |
| `Ctrl+←` / `Ctrl+→` | 上一首 / 下一首macOS 亦支持 `Command+← / →` | | `Ctrl+←` / `Ctrl+→` | 上一首 / 下一首macOS 亦支持 `Command+← / →` |
| `N` / `P` | 下一首 / 上一首 | | `N` / `P` | 下一首 / 上一首 |

View File

@@ -12,6 +12,7 @@
← / → 后退 / 前进 10 秒 ← / → 后退 / 前进 10 秒
Shift+← / → 后退 / 前进 60 秒 Shift+← / → 后退 / 前进 60 秒
↑ / ↓ 音量 +5 / -5 ↑ / ↓ 音量 +5 / -5
Ctrl+↑ / ↓ 快进步长 +1 / -1 秒macOS 亦支持 Command+↑ / ↓)
M 静音 / 恢复 M 静音 / 恢复
Ctrl+← / → 上一首 / 下一首macOS 也支持 Command+← / →) Ctrl+← / → 上一首 / 下一首macOS 也支持 Command+← / →)
N / P 下一首 / 上一首 N / P 下一首 / 上一首
@@ -830,6 +831,7 @@ class MediaPlayerApp(tk.Tk):
self.current_index = -1 self.current_index = -1
self.volume = 80 self.volume = 80
self.rate = 1.0 self.rate = 1.0
self.seek_step = self._load_settings()
self.loop_mode = "list" self.loop_mode = "list"
self._seeking = False self._seeking = False
self._switching_until = 0.0 self._switching_until = 0.0
@@ -963,10 +965,27 @@ class MediaPlayerApp(tk.Tk):
self.seekbar = SeekBar(bottom, command=self._on_seek_command) self.seekbar = SeekBar(bottom, command=self._on_seek_command)
self.seekbar.pack(fill="x") self.seekbar.pack(fill="x")
controls = ttk.Frame(bottom)
controls.pack(fill="x", pady=(4, 0))
self.time_var = tk.StringVar(value="00:00 / --:--") self.time_var = tk.StringVar(value="00:00 / --:--")
self.status_var = tk.StringVar(value="就绪 — 打开文件或按 Ctrl+O") self.status_var = tk.StringVar(value="就绪 — 打开文件或按 Ctrl+O")
ttk.Label(bottom, textvariable=self.time_var).pack(side="left", anchor="w") self.seek_step_var = tk.StringVar(value=str(self.seek_step))
ttk.Label(bottom, textvariable=self.status_var, anchor="e").pack(side="right", fill="x", expand=True) ttk.Label(controls, textvariable=self.time_var).pack(side="left", anchor="w")
ttk.Label(controls, text="快进步长:").pack(side="left", padx=(16, 4))
self.seek_step_spin = ttk.Spinbox(
controls,
from_=1,
to=600,
increment=1,
width=5,
textvariable=self.seek_step_var,
command=self._commit_seek_step,
)
self.seek_step_spin.pack(side="left")
ttk.Label(controls, text="").pack(side="left", padx=(4, 0))
self.seek_step_spin.bind("<Return>", self._on_seek_step_return)
self.seek_step_spin.bind("<FocusOut>", lambda _e: self._commit_seek_step())
ttk.Label(controls, textvariable=self.status_var, anchor="e").pack(side="right", fill="x", expand=True)
def _bind_shortcuts(self): def _bind_shortcuts(self):
shortcuts = [ shortcuts = [
@@ -981,6 +1000,10 @@ class MediaPlayerApp(tk.Tk):
("<Command-Right>", lambda _e: self.next_track()), ("<Command-Right>", lambda _e: self.next_track()),
("<Up>", self._on_up), ("<Up>", self._on_up),
("<Down>", self._on_down), ("<Down>", self._on_down),
("<Control-Up>", lambda _e: self.adjust_seek_step(1)),
("<Control-Down>", lambda _e: self.adjust_seek_step(-1)),
("<Command-Up>", lambda _e: self.adjust_seek_step(1)),
("<Command-Down>", lambda _e: self.adjust_seek_step(-1)),
("<m>", lambda _e: self.toggle_mute()), ("<m>", lambda _e: self.toggle_mute()),
("<M>", lambda _e: self.toggle_mute()), ("<M>", lambda _e: self.toggle_mute()),
("<Control-o>", lambda _e: self.open_files()), ("<Control-o>", lambda _e: self.open_files()),
@@ -1006,20 +1029,29 @@ class MediaPlayerApp(tk.Tk):
("<Return>", lambda _e: self.play_selected()), ("<Return>", lambda _e: self.play_selected()),
] ]
for sequence, handler in shortcuts: for sequence, handler in shortcuts:
self.bind(sequence, handler) wrapped = self._break_handler(handler)
self.listbox.bind(sequence, handler) self.bind(sequence, wrapped)
self.listbox.bind(sequence, wrapped)
self.listbox.bind("<Double-Button-1>", lambda _e: self.play_selected()) self.listbox.bind("<Double-Button-1>", lambda _e: self.play_selected())
@staticmethod
def _break_handler(handler):
"""包装快捷键回调:执行后返回 "break",阻止事件继续冒泡造成重复触发。"""
def run(event):
handler(event)
return "break"
return run
def _on_space(self, _event): def _on_space(self, _event):
self.toggle_play() self.toggle_play()
return "break" return "break"
def _on_left(self, _event): def _on_left(self, _event):
self.seek_relative(-SEEK_STEP) self.seek_relative(-self.seek_step)
return "break" return "break"
def _on_right(self, _event): def _on_right(self, _event):
self.seek_relative(SEEK_STEP) self.seek_relative(self.seek_step)
return "break" return "break"
def _on_up(self, _event): def _on_up(self, _event):
@@ -1118,6 +1150,26 @@ class MediaPlayerApp(tk.Tk):
def _playlist_path(self): def _playlist_path(self):
return Path.home() / ".mediaplayer_playlist.json" return Path.home() / ".mediaplayer_playlist.json"
def _settings_path(self):
return Path.home() / ".mediaplayer_settings.json"
def _load_settings(self):
try:
data = json.loads(self._settings_path().read_text(encoding="utf-8"))
value = int(data.get("seek_step", SEEK_STEP))
except Exception:
value = SEEK_STEP
return value if 1 <= value <= 600 else SEEK_STEP
def _save_settings(self):
try:
self._settings_path().write_text(
json.dumps({"seek_step": self.seek_step}, ensure_ascii=False, indent=2),
encoding="utf-8",
)
except Exception as exc:
print("保存设置失败:", exc)
def _save_playlist(self): def _save_playlist(self):
try: try:
data = {"playlist": list(self.playlist), "current_index": self.current_index} data = {"playlist": list(self.playlist), "current_index": self.current_index}
@@ -1228,6 +1280,36 @@ class MediaPlayerApp(tk.Tk):
return return
self.seek_to(pos + seconds * 1000) self.seek_to(pos + seconds * 1000)
def _commit_seek_step(self):
raw = self.seek_step_var.get().strip()
try:
value = int(float(raw))
except ValueError:
value = 0
if not 1 <= value <= 600:
self.seek_step_var.set(str(self.seek_step))
self.status_var.set("快进步长需为 1-600 之间的整数")
return
if value != self.seek_step:
self.seek_step = value
self._save_settings()
self.status_var.set(f"快进步长已设为 {value} 秒(已保存)")
def adjust_seek_step(self, delta):
value = max(1, min(600, self.seek_step + delta))
if value == self.seek_step:
self.status_var.set(f"快进步长已到{'上限' if delta > 0 else '下限'}{value} 秒)")
return
self.seek_step = value
self.seek_step_var.set(str(value))
self._save_settings()
self.status_var.set(f"快进步长已设为 {value} 秒(已保存)")
def _on_seek_step_return(self, _event):
self._commit_seek_step()
self.focus_set()
return "break"
def seek_to(self, ms): def seek_to(self, ms):
ms = max(0, int(ms)) ms = max(0, int(ms))
if not self.engine.seek(ms): if not self.engine.seek(ms):