引言
在日常办公或娱乐中,定时关机功能总能解决一些 “小确幸” 需求:
- 睡前下载文件后自动关机节省电量
- 远程办公时设置任务后无需留守
- 给孩子设定屏幕使用时间上限
- 50个赞出一期 : 取消关机加密码
本文将用 Python 的 Tkinter 库开发一个跨平台定时关机工具,包含图形化界面、倒计时显示和快捷键操作,文末附完整源码与优化思路。
开发原因 : 我爱玩火影忍者但是不喜欢打周胜,一般一次需要2个小时我就一直等,期间想出去玩,又怕电脑待机消耗电费,长时间让电脑运行,所以开发了这个小.exe文件,多么疼的礼物
突发奇想
一、功能与界面展示
核心功能
- 倒计时设置:输入分钟数后开始定时关机
- 状态可视化:实时显示剩余时间与操作状态
- 快捷操作:支持 Enter 键开始、Esc 键取消
- 跨平台兼容:
- Windows 系统:调用系统关机命令实现真实关机
- 支持 Windows、Linux、macOS 三大系统,附完整兼容代码与深度优化技巧。
- 其他系统:提示 “模拟关机” 便于调试
界面预览
一、环境与模块导入
python
运行
import os # 调用系统命令(如关机)
import sys # 获取系统信息(如平台类型)
import tkinter as tk
from tkinter import messagebox, ttk # 图形界面组件与提示框
- Tkinter:Python 内置 GUI 库,用于创建窗口、按钮等组件
- ttk:Tkinter 的主题化组件库,提供更美观的按钮、输入框等样式
- os/sys:用于判断操作系统类型(Windows/Linux/macOS)并执行对应关机命令
二、界面初始化与布局
1. 窗口基础设置
python
运行
class ShutdownApp:
def __init__(self, root):
self.root = root
self.root.title("🌙 定时关机工具") # 窗口标题
self.root.geometry("420x400") # 窗口尺寸(宽x高)
self.center_window(420, 400) # 窗口居中函数
self.root.configure(bg='#1e1e2f') # 背景色(深紫色)
- 窗口居中实现:
python
运行
def center_window(self, width, height): screen_w = self.root.winfo_screenwidth() # 获取屏幕宽度 screen_h = self.root.winfo_screenheight() # 获取屏幕高度 x = (screen_w - width) // 2 # 计算居中x坐标 y = (screen_h - height) // 2 # 计算居中y坐标 self.root.geometry(f"{width}x{height}+{x}+{y}")
- 原理:通过屏幕分辨率计算窗口左上角坐标,实现居中显示。
2. 界面组件创建
(1)输入与交互区
python
运行
# 标题标签
self.title_label = tk.Label(root, text="请输入关机倒计时(分钟)",
font=("微软雅黑", 14), bg='#1e1e2f', fg='white')
self.title_label.pack(pady=20) # pady=20:上下边距20像素
# 输入框
self.input_entry = tk.Entry(root, font=("Arial", 16), justify='center')
self.input_entry.pack(pady=10)
self.input_entry.focus_set() # 自动聚焦输入框,方便直接输入
# 快捷键提示
self.hint_label = tk.Label(root, text="↩ Enter 开始 ⎋ Esc 取消",
font=("微软雅黑", 11), fg='#999')
self.hint_label.pack()
- 关键细节:
justify='center'
:输入框内容居中显示focus_set()
:窗口打开时自动聚焦输入框,提升操作效率
(2)按钮区
python
运行
style = ttk.Style()
style.theme_use("clam") # 使用轻量级主题
style.configure("TButton",
font=("Arial", 14), # 字体大小
padding=6, # 内边距(上下左右)
foreground='white', # 文字颜色
background='#3a86ff' # 按钮背景色(天蓝色)
)
self.start_button = ttk.Button(root, text="🌟 开始定时关机",
command=self.start_shutdown)
self.start_button.pack(pady=12)
self.cancel_button = ttk.Button(root, text="✖️ 取消关机",
command=self.cancel_shutdown)
self.cancel_button.pack(pady=8)
self.cancel_button.config(state='disabled') # 初始状态为禁用
- ttk 按钮优势:
- 支持自定义字体、内边距、背景色,比原生
tk.Button
更美观 state='disabled'
:初始时取消按钮不可用,避免误操作
- 支持自定义字体、内边距、背景色,比原生
(3)状态显示与加载遮罩
python
运行
# 状态标签(显示剩余时间/操作结果)
self.status_label = tk.Label(root, text="状态:尚未设置",
font=("微软雅黑", 13), fg='#ffeb3b') # 黄色文字
self.status_label.pack(pady=20)
# 加载遮罩(设置关机时显示)
self.overlay = tk.Frame(root, width=420, height=400, bg="#000000")
self.overlay.place_forget() # 初始隐藏
self.loading_label = tk.Label(self.overlay, text="⏳ 正在设置,请稍候...",
bg="#000000", fg="white")
self.loading_label.place(relx=0.5, rely=0.5, anchor='center') # 居中显示
- 加载遮罩作用:
- 在调用系统关机命令时显示半透明黑色遮罩,提示用户操作中
place_forget()
:隐藏组件,place(x=0,y=0)
:显示组件
三、核心功能逻辑
1. 开始定时关机
python
运行
def start_shutdown(self):
minutes = self.input_entry.get().strip() # 获取输入内容并去空格
if not minutes.isdigit() or int(minutes) <= 0:
messagebox.showwarning("输入错误", "请输入正整数分钟数!")
return # 输入无效时直接返回
# 初始化倒计时参数
self.shutdown_time = int(minutes) * 60 # 转换为秒
self.remaining_time = self.shutdown_time
self.countdown_active = True # 标记倒计时已激活
# 更新界面状态
self.status_label.config(text=f"⏳ 定时关机已设置:{minutes} 分钟")
self.start_button.config(state='disabled') # 禁用开始按钮
self.cancel_button.config(state='normal') # 启用取消按钮
self.show_loading() # 显示加载遮罩
# 调用系统关机命令(仅Windows有效,其他系统模拟)
if sys.platform.startswith("win"):
os.system(f"shutdown -s -t {self.shutdown_time}") # Windows关机命令
else:
self.status_label.config(text="模拟关机(非Windows系统)")
self.update_ui() # 启动倒计时UI更新
- 关键逻辑:
- 输入验证:确保用户输入正整数,否则弹出警告框
- 系统兼容性:
- Windows:使用
shutdown -s -t [秒数]
命令 - 其他系统(Linux/macOS):仅显示模拟提示(需手动扩展命令)
- Windows:使用
- 加载遮罩:通过
show_loading()
显示 1.5 秒后自动隐藏
2. 倒计时 UI 更新
python
运行
def update_ui(self):
if self.remaining_time > 0 and self.countdown_active:
self.remaining_time -= 1 # 每秒减少1秒
mins, secs = divmod(self.remaining_time, 60) # 转换为分钟和秒
self.status_label.config(text=f"⏱ 剩余时间:{mins}分 {secs}秒")
# 每隔1秒调用一次自身,实现实时刷新(非阻塞)
self.timer_after_id = self.root.after(1000, self.update_ui)
elif self.countdown_active:
self.status_label.config(text="⚠️ 系统即将关机...") # 倒计时结束提示
- Tkinter 定时器原理:
root.after(1000, self.update_ui)
:每隔 1000 毫秒(1 秒)调用一次update_ui
- 避免使用
time.sleep()
,防止界面卡顿
3. 取消关机任务
def cancel_shutdown(self):
if not self.countdown_active:
return # 无任务时直接返回
confirm = messagebox.askyesno("确认取消", "是否真的要取消定时关机?")
if confirm:
self.countdown_active = False # 停止倒计时
if self.timer_after_id:
self.root.after_cancel(self.timer_after_id) # 取消定时器
# 调用系统取消命令(仅Windows有效)
if sys.platform.startswith("win"):
os.system("shutdown -a") # Windows取消关机命令
self.status_label.config(text="✅ 已取消定时关机")
else:
self.status_label.config(text="✅ 模拟取消成功")
self.reset_ui() # 重置界面状态
- 安全机制:
- 使用
askyesno
确认框防止误操作 after_cancel
确保定时器被正确终止- 重置界面状态(恢复按钮可用状态、清空剩余时间)
- 使用
4. 窗口关闭处理
def on_close(self):
if self.countdown_active:
# 有关机任务时提示用户确认退出
if messagebox.askokcancel("退出", "当前有定时关机任务,确定要退出吗?"):
self.cancel_shutdown() # 退出前自动取消任务
self.root.destroy()
else:
self.root.destroy() # 无任务时直接关闭窗口
- 用户体验优化:
- 避免用户误关窗口导致关机任务残留
- 退出时自动取消任务,确保系统安全
四、系统兼容性与扩展建议
1. 当前兼容性
系统 | 关机命令 | 功能支持情况 |
---|---|---|
Windows | shutdown -s -t | 完全支持 |
Linux/macOS | 未实现 | 仅显示模拟提示 |
2. 扩展为跨平台的改进方向
# 示例:增加Linux/macOS关机命令(需管理员权限)
if sys.platform.startswith("linux"):
os.system(f"shutdown -h +{minutes}") # +分钟数后关机
elif sys.platform == "darwin": # macOS
os.system(f"shutdown -h {minutes}分钟后") # 需调整命令格式
- 注意事项:
- Linux/macOS 执行关机命令需
sudo
权限,需添加权限检测 - 使用
subprocess
替代os.system
以更好处理命令输出
- Linux/macOS 执行关机命令需
五、代码总结
1. 核心流程
- 用户输入分钟数 → 2. 验证输入有效性 → 3. 调用系统关机命令 → 4. 启动倒计时 UI 更新 → 5. 支持中途取消或正常关机
2. 技术要点
- Tkinter 界面布局:使用
pack
布局管理器,配合边距参数实现整洁排版 - 系统命令交互:通过
os.system
执行关机 / 取消命令,仅限 Windows 有效 - 非阻塞倒计时:利用
root.after
实现每秒刷新,保持界面流畅 -
3.代码最终呈现
-
import os import sys import tkinter as tk from tkinter import messagebox, ttk class ShutdownApp: def __init__(self, root): self.root = root self.root.title("🌙 定时关机工具") self.root.geometry("420x400") self.center_window(420, 400) self.root.configure(bg='#1e1e2f') self.shutdown_time = None self.remaining_time = 0 self.countdown_active = False self.timer_after_id = None style = ttk.Style() style.theme_use("clam") style.configure("TButton", font=("Arial", 14), padding=6, foreground='white', background='#3a86ff') # 标题 self.title_label = tk.Label(root, text="请输入关机倒计时(分钟)", font=("微软雅黑", 14), bg='#1e1e2f', fg='white') self.title_label.pack(pady=20) # 输入框 self.input_entry = tk.Entry(root, font=("Arial", 16), justify='center') self.input_entry.pack(pady=10) self.input_entry.focus_set() # 自动获取焦点 # 快捷键提示 self.hint_label = tk.Label(root, text="↩ Enter 开始 ⎋ Esc 取消", font=("微软雅黑", 11), bg='#1e1e2f', fg='#999') self.hint_label.pack() # 按钮区 self.start_button = ttk.Button(root, text="🌟 开始定时关机", command=self.start_shutdown) self.start_button.pack(pady=12) self.cancel_button = ttk.Button(root, text="✖️ 取消关机", command=self.cancel_shutdown) self.cancel_button.pack(pady=8) self.cancel_button.config(state='disabled') # 状态显示 self.status_label = tk.Label(root, text="状态:尚未设置", font=("微软雅黑", 13), bg='#1e1e2f', fg='#ffeb3b') self.status_label.pack(pady=20) # 加载遮罩 self.overlay = tk.Frame(root, width=420, height=400, bg="#000000") self.overlay.place_forget() self.loading_label = tk.Label(self.overlay, text="⏳ 正在设置,请稍候...", font=("微软雅黑", 16), bg="#000000", fg="white") self.loading_label.place(relx=0.5, rely=0.5, anchor='center') # 绑定关闭与快捷键 self.root.protocol("WM_DELETE_WINDOW", self.on_close) self.root.bind("<Return>", lambda e: self.start_shutdown()) self.root.bind("<Escape>", lambda e: self.cancel_shutdown()) def center_window(self, width, height): screen_w = self.root.winfo_screenwidth() screen_h = self.root.winfo_screenheight() x = (screen_w - width) // 2 y = (screen_h - height) // 2 self.root.geometry(f"{width}x{height}+{x}+{y}") def show_loading(self): self.overlay.place(x=0, y=0) self.root.after(1500, self.hide_loading) def hide_loading(self): self.overlay.place_forget() def start_shutdown(self): minutes = self.input_entry.get().strip() if not minutes.isdigit() or int(minutes) <= 0: messagebox.showwarning("输入错误", "请输入正整数分钟数!") return self.shutdown_time = int(minutes) * 60 self.remaining_time = self.shutdown_time self.countdown_active = True self.status_label.config(text=f"⏳ 定时关机已设置:{minutes} 分钟") self.start_button.config(state='disabled') self.cancel_button.config(state='normal') self.show_loading() if sys.platform.startswith("win"): os.system(f"shutdown -s -t {self.shutdown_time}") else: self.status_label.config(text="模拟关机(非Windows系统)") self.update_ui() def update_ui(self): if self.remaining_time > 0 and self.countdown_active: self.remaining_time -= 1 mins, secs = divmod(self.remaining_time, 60) self.status_label.config(text=f"⏱ 剩余时间:{mins}分 {secs}秒") self.timer_after_id = self.root.after(1000, self.update_ui) elif self.countdown_active: self.status_label.config(text="⚠️ 系统即将关机...") def cancel_shutdown(self): if not self.countdown_active: return confirm = messagebox.askyesno("确认取消", "是否真的要取消定时关机?") if confirm: self.countdown_active = False if self.timer_after_id: self.root.after_cancel(self.timer_after_id) if sys.platform.startswith("win"): os.system("shutdown -a") self.status_label.config(text="✅ 已取消定时关机") else: self.status_label.config(text="✅ 模拟取消成功") self.reset_ui() def reset_ui(self): self.start_button.config(state='normal') self.cancel_button.config(state='disabled') self.remaining_time = 0 self.timer_after_id = None self.countdown_active = False def on_close(self): if self.countdown_active: if messagebox.askokcancel("退出", "当前有定时关机任务,确定要退出吗?"): self.cancel_shutdown() self.root.destroy() else: self.root.destroy() if __name__ == "__main__": root = tk.Tk() app = ShutdownApp(root) root.mainloop()
六.代码打包为小应用.exe
-
1.找到代码所在地
-
2. 安装打包工具
pyinstaller
在上面的图中打开终端,输入
-
# 使用pip安装(确保已安装Python和pip) pip install pyinstaller
直接在命令行执行的打包命令
bash
pyinstaller --noconsole --onedir --windowed --icon=shutdown_icon.ico --name="定时关机工具" shutdown_tool.py
参数说明
参数 | 作用 |
---|---|
--onedir | 打包为多文件模式(生成一个包含所有依赖的文件夹) |
--noconsole | 隐藏终端窗口(适用于 GUI 程序) |
--windowed | Windows 平台专用,确保无终端窗口 |
--icon=shutdown_icon.ico | 指定自定义图标(需替换为你的图标路径) |
--name="定时关机工具" | 指定输出的文件夹名和可执行文件名 |
shutdown_tool.py | 你的主 Python 脚本文件名 |
最终效果
- 注意需要,图标和代码文件放在同一个文件夹里面
推荐一个网站 免费 jpg png 等 转化为 ico 适合做应用图标 建议大小400*400
Convert your image to ICO format