【PPT】PPT播放倒计时控制器:演讲者的智能时间管家
- 2026-11-13 11:21:30
【PPT】PPT播放倒计时控制器:演讲者的智能时间管家


参数设置区域:


“一款自动检测PPT全屏播放、启动倒计时并在结束时退出全屏的辅助工具。它在屏幕右上角显示半透明倒计时窗口,最后10秒在屏幕中央显示大数字提示,并支持自定义提示时间和文本,帮助演讲者精准掌控时间。”
01
—
主要功能
自动检测:PPT进入全屏模式即启动倒计时。
可调时长:倒计时时间1~3600秒自由设置。
视觉提示:
右上角小窗:数字颜色绿(正常)→黄(接近提示时间)→红(最后10秒)。
中央大数字:最后10秒显示10~1,颜色由浅红渐变至深红。
自定义提醒:可设置剩余指定秒数时弹出提示框(3秒后自动消失),提示文本支持
{seconds}占位符。暂停/恢复:随时暂停监控,暂停期间PPT全屏不触发倒计时。
自动退出:倒计时结束时自动发送ESC键退出PPT全屏。
02
—
安装要求
操作系统:Windows
Python环境:Python 3.6+
依赖库:安装
pywin32和keyboard
pip install pywin32 keyboard【注】Python脚本生成可执行文件后可直接在Windows环境下运行使用。
03
—
使用步骤
1. 启动程序:运行python PPT倒计时控制器.py。
2. 设置参数(可选):
在控制面板输入倒计时总秒数、提示时间秒数(0为不提示)、提示文本(含
{seconds})。点击“应用所有设置”保存。

3.开始监控:点击“开始监控”,状态变为“运行中”。

4. 播放PPT:进入PPT全屏模式,倒计时自动开始。

5. 观看提示:
右上角显示剩余时间,颜色变化。
最后10秒中央显示大数字。
到达提示时间时弹出自定义信息框。

6. 结束:倒计时归零,PPT自动退出全屏,所有提示窗口消失。
7. 暂停/退出:点击“暂停监控”可暂停检测;点击“退出程序”关闭软件。

04
—
程序代码
关键核心代码:
import win32guiimport win32conimport win32apiimport timeimport threadingimport queueimport keyboardimport tkinter as tk# ---------- 右上角小窗口 ----------class CornerDisplay:def __init__(self, master):self.master = masterself.window = Noneself.q = queue.Queue()master.after(100, self._process_queue)def _create(self):self.window = tk.Toplevel(self.master)sw = self.window.winfo_screenwidth()self.window.geometry(f"80x30+{sw-85}+5")self.window.attributes('-topmost', True, '-alpha', 0.9)self.window.overrideredirect(True)self.window.configure(bg='black')self.label = tk.Label(self.window, font=('Arial',14,'bold'), fg='white', bg='black')self.label.pack(expand=True, fill='both')self.window.withdraw()def _process_queue(self):try:while True:cmd = self.q.get_nowait()if cmd[0] == 'show':if not self.window:self._create()self.label.config(text=cmd[1], fg=cmd[2])self.window.deiconify()elif cmd[0] == 'hide':if self.window:self.window.withdraw()elif cmd[0] == 'destroy':if self.window:self.window.destroy()returnexcept queue.Empty:passself.master.after(100, self._process_queue)def show(self, text, color):self.q.put(('show', text, color))def hide(self):self.q.put(('hide',))def destroy(self):self.q.put(('destroy',))# ---------- 中央大数字 ----------class CenterDisplay:def __init__(self, master):self.master = masterself.window = Noneself.q = queue.Queue()master.after(100, self._process_queue)def _create(self):self.window = tk.Toplevel(self.master)sw, sh = self.window.winfo_screenwidth(), self.window.winfo_screenheight()self.window.geometry(f"300x300+{(sw-300)//2}+{(sh-300)//2}")self.window.attributes('-topmost', True)self.window.overrideredirect(True)self.window.configure(bg='white')self.window.wm_attributes('-transparentcolor', 'white')self.label = tk.Label(self.window, font=('Arial',200,'bold'), bg='white')self.label.pack(expand=True, fill='both')self.window.withdraw()def _process_queue(self):try:while True:cmd = self.q.get_nowait()if cmd[0] == 'show':if not self.window:self._create()self.label.config(text=cmd[1], fg=cmd[2])self.window.deiconify()elif cmd[0] == 'hide':if self.window:self.window.withdraw()elif cmd[0] == 'destroy':if self.window:self.window.destroy()returnexcept queue.Empty:passself.master.after(100, self._process_queue)def show(self, num):colors = {10:'#FF9999',9:'#FF8888',8:'#FF7777',7:'#FF6666',6:'#FF5555',5:'#FF4444',4:'#FF3333',3:'#FF2222',2:'#FF1111',1:'#FF0000',0:'#FF0000'}self.q.put(('show', str(num), colors.get(num,'#FF0000')))def hide(self):self.q.put(('hide',))def destroy(self):self.q.put(('destroy',))# ---------- 提示窗口 ----------class AlertDisplay:def __init__(self, master):self.master = masterself.window = Noneself.q = queue.Queue()self.template = "距汇报结束还剩下{seconds}秒"master.after(100, self._process_queue)def _create(self):self.window = tk.Toplevel(self.master)sw = self.window.winfo_screenwidth()self.window.geometry(f"350x100+{sw-355}+40")self.window.attributes('-topmost', True, '-alpha', 0.85)self.window.overrideredirect(True)self.window.configure(bg='black')self.label = tk.Label(self.window, font=('Microsoft YaHei',16,'bold'),fg='#FFD700', bg='black', wraplength=320)self.label.pack(expand=True, fill='both', padx=10, pady=10)self.window.withdraw()self.timer = Nonedef _process_queue(self):try:while True:cmd = self.q.get_nowait()if cmd[0] == 'show':if not self.window:self._create()self.label.config(text=cmd[1])self.window.deiconify()if self.timer:self.window.after_cancel(self.timer)self.timer = self.window.after(3000, self.hide)elif cmd[0] == 'hide':if self.window:self.window.withdraw()elif cmd[0] == 'destroy':if self.window:if self.timer:self.window.after_cancel(self.timer)self.window.destroy()returnexcept queue.Empty:passself.master.after(100, self._process_queue)def show(self, seconds):text = self.template.replace("{seconds}", str(seconds))self.q.put(('show', text))def hide(self):self.q.put(('hide',))def destroy(self):self.q.put(('destroy',))def set_template(self, template):self.template = template# ---------- 监控核心 ----------class PPTMonitor:def __init__(self, master):self.master = masterself.corner = CornerDisplay(master)self.center = CenterDisplay(master)self.alert = AlertDisplay(master)self.total = 30self.alert_time = 20self.alert_text = "距汇报结束还剩下{seconds}秒"self.running = Falseself.paused = Falseself.stop_event = threading.Event()self.pause_event = threading.Event()self.pause_event.set()self.thread = Nonedef set_params(self, total, alert_time, alert_text):self.total = max(1, min(total, 3600))self.alert_time = max(0, min(alert_time, 3600))self.alert.set_template(alert_text)def find_ppt(self):def cb(hwnd, lst):if win32gui.IsWindowVisible(hwnd):title = win32gui.GetWindowText(hwnd).lower()if any(k in title for k in ['powerpoint','幻灯片','.ppt','.pptx','ppt -']):lst.append(hwnd)return Truelst = []win32gui.EnumWindows(cb, lst)return lst[0] if lst else Nonedef is_fullscreen(self, hwnd):try:l,t,r,b = win32gui.GetWindowRect(hwnd)sw = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)sh = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)return (l<=2 and t<=2 and r>=sw-2 and b>=sh-2)except:return Falsedef countdown_loop(self):self.corner.show(self._fmt(self.total), self._color(self.total))self.alert_shown = Falsefor i in range(self.total, 0, -1):if self.stop_event.is_set() or not self.running:breakif self.paused:self.corner.hide()self.center.hide()self.alert.hide()self.pause_event.clear()while self.paused and self.running and not self.stop_event.is_set():self.pause_event.wait(0.2)if not self.paused:self.pause_event.set()self.corner.show(self._fmt(i), self._color(i))if i<=10:self.center.show(i)self.corner.show(self._fmt(i), self._color(i))if i==self.alert_time and not self.alert_shown and self.alert_time>0:self.alert.show(i)self.alert_shown = Trueif i<=10:self.center.show(i)else:self.center.hide()time.sleep(1)self.corner.hide()self.center.hide()self.alert.hide()if self.running and not self.stop_event.is_set():self._exit_fullscreen()def _fmt(self, sec):h = sec//3600m = (sec%3600)//60s = sec%60return f"{h:02d}:{m:02d}:{s:02d}" if h else f"{m:02d}:{s:02d}"def _color(self, sec):if sec <= 10:return '#FF0000'elif sec <= self.alert_time:return '#FFFF00'else:return '#00FF00'def _exit_fullscreen(self):hwnd = self.find_ppt()if hwnd:win32gui.SetForegroundWindow(hwnd)time.sleep(0.3)keyboard.send('esc')time.sleep(0.5)def monitor_loop(self):while self.running:hwnd = self.find_ppt()if hwnd and self.is_fullscreen(hwnd):if not self.is_fullscreen_prev:self.is_fullscreen_prev = Trueif not self.paused:self.stop_event.clear()self.thread = threading.Thread(target=self.countdown_loop, daemon=True)self.thread.start()else:if self.is_fullscreen_prev:self.is_fullscreen_prev = Falseself.stop_event.set()if self.thread:self.thread.join(timeout=1)self.stop_event.clear()time.sleep(1)def start(self):if self.running:returnself.running = Trueself.is_fullscreen_prev = Falseself.stop_event.clear()threading.Thread(target=self.monitor_loop, daemon=True).start()def stop(self):self.running = Falseself.stop_event.set()self.pause_event.set()if self.thread:self.thread.join(timeout=1)self.corner.destroy()self.center.destroy()self.alert.destroy()def pause_resume(self):self.paused = not self.pausedif self.paused:self.pause_event.clear()else:self.pause_event.set()return self.paused# ---------- 简单启动示例 ----------if __name__ == "__main__":root = tk.Tk()root.withdraw()monitor = PPTMonitor(root)monitor.set_params(30, 20, "距离结束还剩{seconds}秒")monitor.start()print("监控已启动,按 Ctrl+C 停止")try:root.mainloop()except KeyboardInterrupt:monitor.stop()root.destroy()
本文来自网友投稿或网络内容,如有侵犯您的权益请联系我们删除,联系邮箱:wyl860211@qq.com 。