Python Tkinter中thread.join()未正常工作问题求助
Tkinter中thread.join()未按预期工作的问题解决
问题根源
你在Tkinter主线程中调用了thread.join(),这会直接阻塞Tkinter的主事件循环,导致整个GUI程序卡死,后续的print("worked")根本没有执行机会。同时你创建的视频/音频线程只是启动播放动作后立即结束,join()本应快速完成,但主线程被阻塞后事件循环停摆,反而引发程序无响应。
另外你的VideoPlayerWithSound类继承了threading.Thread但并未实际使用该线程能力,属于冗余设计,反而容易造成误解。
修复方案
1. 移除主线程中的join()调用
主线程必须保持Tkinter事件循环的运行,绝对不能被join()这类阻塞操作占用。
2. 使用回调机制监听播放结束事件
分别为视频和音频设置播放结束的回调,当两者都完成后再执行后续操作。
修改后的主程序代码
self.path = r'src\files\iki' # 新增:跟踪播放完成状态 self.video_finished = False self.sound_finished = False self.play_video(self.path) def play_video(self, path): self.video_thread = threading.Thread(target=self.video_player.play_video, args=(path + ".mp4",)) self.sound_thread = threading.Thread(target=self.video_player.play_sound, args=(path + ".mp3",)) self.sound_thread.start() self.video_thread.start() # 视频播放结束回调 def on_video_end(self, event): self.video_finished = True self._check_all_finished() # 音频播放结束回调 def on_sound_end(self): self.sound_finished = True self._check_all_finished() # 检查是否两者都播放完毕 def _check_all_finished(self): if self.video_finished and self.sound_finished: print("worked")
修改后的脚本文件代码
import threading import tkinter as tk import pygame from tkVideoPlayer import TkinterVideo class VideoPlayerWithSound: # 移除不必要的threading.Thread继承 def __init__(self, parent_frame, sound_end_callback): self.parent_frame = parent_frame self.sound_end_callback = sound_end_callback self.videoplayer = TkinterVideo(master=self.parent_frame, scaled=True) self.videoplayer.pack(expand=True, fill="both") pygame.init() def play_video(self, video_path): self.videoplayer.load(video_path) # 绑定视频结束事件,通知主线程 self.videoplayer.bind("<<End>>", lambda e: self.parent_frame.event_generate("<<VideoEnd>>")) self.videoplayer.play() def play_sound(self, sound_path): pygame.mixer.music.load(sound_path) pygame.mixer.music.play() # 在子线程中监听音频结束,避免阻塞主线程 threading.Thread(target=self._listen_sound_finish, daemon=True).start() def _listen_sound_finish(self): while pygame.mixer.music.get_busy(): pygame.time.wait(100) # 音频结束后触发回调 self.sound_end_callback()
主程序初始化VideoPlayerWithSound时的绑定
# 初始化时传入音频结束回调 self.video_player = VideoPlayerWithSound(parent_frame=self, sound_end_callback=self.on_sound_end) # 绑定视频结束事件到主程序的回调 self.bind("<<VideoEnd>>", self.on_video_end)
核心要点
- Tkinter是单线程模型,所有GUI相关操作必须在主线程执行,主线程不能被长时间阻塞。
- 视频播放结束通过TkinterVideo内置的
<<End>>事件监听,音频结束通过子线程循环检查pygame.mixer.music.get_busy()实现。 - 用状态标志位跟踪两个媒体的播放进度,当两者都完成时再执行后续逻辑。
内容的提问来源于stack exchange,提问作者Umut Topalak
相关产品推荐
相关产品推荐

