用 Python 打造极简定时关机工具:附 Tkinter 界面源码与实战教程(含 Linux/macOS 支持)简单手把手教你应用制作

引言

在日常办公或娱乐中,定时关机功能总能解决一些 “小确幸” 需求:

  • 睡前下载文件后自动关机节省电量
  • 远程办公时设置任务后无需留守
  • 给孩子设定屏幕使用时间上限
  • 50个赞出一期 : 取消关机加密码

本文将用 Python 的 Tkinter 库开发一个跨平台定时关机工具,包含图形化界面、倒计时显示和快捷键操作,文末附完整源码与优化思路。

开发原因 : 我爱玩火影忍者但是不喜欢打周胜,一般一次需要2个小时我就一直等,期间想出去玩,又怕电脑待机消耗电费,长时间让电脑运行,所以开发了这个小.exe文件,多么疼的礼物

突发奇想

一、功能与界面展示

核心功能

  1. 倒计时设置:输入分钟数后开始定时关机
  2. 状态可视化:实时显示剩余时间与操作状态
  3. 快捷操作:支持 Enter 键开始、Esc 键取消
  4. 跨平台兼容
    • 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):仅显示模拟提示(需手动扩展命令)
    • 加载遮罩:通过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. 当前兼容性
系统关机命令功能支持情况
Windowsshutdown -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以更好处理命令输出

五、代码总结

1. 核心流程
  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 程序)
--windowedWindows 平台专用,确保无终端窗口
--icon=shutdown_icon.ico指定自定义图标(需替换为你的图标路径)
--name="定时关机工具"指定输出的文件夹名和可执行文件名
shutdown_tool.py你的主 Python 脚本文件名

最终效果 

  • 注意需要,图标和代码文件放在同一个文件夹里面

推荐一个网站 免费 jpg png 等 转化为 ico 适合做应用图标 建议大小400*400

Convert your image to ICO format

      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

      当前余额3.43前往充值 >
      需支付:10.00
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包

      打赏作者

      智极Hub

      你的鼓励将是我创作的最大动力

      ¥1 ¥2 ¥4 ¥6 ¥10 ¥20
      扫码支付:¥1
      获取中
      扫码支付

      您的余额不足,请更换扫码支付或充值

      打赏作者

      实付
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

      余额充值