commit fed6c361a5c7ef0c21ce20840e150ccab2f35da1 Author: 李如威 Date: Wed Oct 22 10:50:00 2025 +0800 feat: 初始化项目 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b7eb2b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,91 @@ +# Byte-compiled / optimized / DLL files[1](@ref)[3](@ref)[8](@ref) +__pycache__/ +*.py[cod] +*$py.class +*.pyc +*.so + +# PyInstaller distribution / packaging[1](@ref)[3](@ref)[8](@ref) +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller specific files[1](@ref)[3](@ref)[8](@ref) +*.manifest +*.spec + +# Installer logs[1](@ref)[3](@ref)[8](@ref) +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports[1](@ref)[3](@ref)[8](@ref) +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Virtual environments[1](@ref)[2](@ref)[7](@ref) +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# macOS specific files[1](@ref)[2](@ref)[6](@ref) +.DS_Store +.AppleDouble +.LSOverride +Icon +._* +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# IDE and editor files[1](@ref)[4](@ref)[6](@ref) +.idea/ +.vscode/ +*.swp +*.swo +*~ +.ropeproject +.spyderproject +.spyproject + +# Other common files +*.log +*.tmp +*.bak diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..4eba2a6 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13.0 diff --git a/README.md b/README.md new file mode 100644 index 0000000..bb04e67 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +## 打包 + +在 windows 中打开 powersehll 执行下面命令 + +```shell +# 安装依赖 +pip3 install -r requirements.txt +# 打包 +python3 -m PyInstaller --onefile --windowed --icon=app.ico --name=ShutdownTimer app.py +``` + diff --git a/app.ico b/app.ico new file mode 100644 index 0000000..e2ebfea Binary files /dev/null and b/app.ico differ diff --git a/app.py b/app.py new file mode 100644 index 0000000..193203b --- /dev/null +++ b/app.py @@ -0,0 +1,147 @@ +import tkinter as tk +from tkinter import ttk, messagebox +import threading +import os +import time + + +class ShutdownTimerApp: + def __init__(self, root): + self.root = root + self.root.title("定时关机程序") + self.root.geometry("400x280") + self.root.minsize(400, 280) # 设置最小尺寸防止窗口过小 + self.root.resizable(False, False) + + # 倒计时线程控制 + self.is_running = False + self.timer_thread = None + + self.create_widgets() + + def create_widgets(self): + # 主框架 + main_frame = ttk.Frame(self.root, padding="20") + main_frame.pack(fill=tk.BOTH, expand=True) + + # 时间输入框架 + time_frame = ttk.LabelFrame(main_frame, text="设置关机时间") + time_frame.pack(fill=tk.X, pady=10) + + # 时间输入和单位选择 + input_frame = ttk.Frame(time_frame) + input_frame.pack(fill=tk.X, pady=10) + + # 时间输入框 + ttk.Label(input_frame, text="时间:").grid(row=0, column=0, padx=5) + self.time_var = tk.StringVar(value="10") + self.time_entry = ttk.Entry(input_frame, textvariable=self.time_var, width=10) + self.time_entry.grid(row=0, column=1, padx=5) + + # 单位选择 + ttk.Label(input_frame, text="单位:").grid(row=0, column=2, padx=5) + self.unit_var = tk.StringVar(value="分钟") + self.unit_combo = ttk.Combobox(input_frame, textvariable=self.unit_var, values=["秒", "分钟", "小时"], state="readonly", width=8) + self.unit_combo.grid(row=0, column=3, padx=5) + + # 状态显示 + self.status_var = tk.StringVar(value="等待设置时间...") + self.status_label = ttk.Label(main_frame, textvariable=self.status_var, font=("Arial", 10)) + self.status_label.pack(pady=10) + + # 倒计时显示 + self.countdown_var = tk.StringVar(value="00:00:00") + self.countdown_label = ttk.Label(main_frame, textvariable=self.countdown_var, font=("Arial", 16, "bold")) + self.countdown_label.pack(pady=5) + + # 按钮框架 + button_frame = ttk.Frame(main_frame) + button_frame.pack(pady=15) + + # 启动按钮 + self.start_button = ttk.Button(button_frame, text="启动关机定时", command=self.start_shutdown_timer) + self.start_button.pack(side=tk.LEFT, padx=5) + + # 取消按钮 + self.cancel_button = ttk.Button(button_frame, text="取消定时", command=self.cancel_shutdown_timer, state="disabled") + self.cancel_button.pack(side=tk.LEFT, padx=5) + + def start_shutdown_timer(self): + if self.is_running: + return + + try: + # 获取输入的时间值 + time_value = float(self.time_var.get()) + if time_value <= 0: + raise ValueError("时间必须大于0") + + # 根据单位转换为秒 + unit = self.unit_var.get() + if unit == "秒": + total_seconds = time_value + elif unit == "分钟": + total_seconds = time_value * 60 + else: # 小时 + total_seconds = time_value * 3600 + + # 更新状态 + self.is_running = True + self.start_button.config(state="disabled") + self.cancel_button.config(state="normal") + self.status_var.set(f"定时已启动 - {time_value} {unit}后关机") + + # 启动倒计时线程 + self.timer_thread = threading.Thread(target=self.countdown_thread, args=(total_seconds,)) + self.timer_thread.daemon = True + self.timer_thread.start() + + except ValueError as e: + messagebox.showerror("输入错误", f"请输入有效的数字: {str(e)}") + + def cancel_shutdown_timer(self): + self.is_running = False + self.start_button.config(state="normal") + self.cancel_button.config(state="disabled") + self.status_var.set("定时已取消") + self.countdown_var.set("00:00:00") + + def countdown_thread(self, total_seconds): + remaining_seconds = total_seconds + + while remaining_seconds > 0 and self.is_running: + # 更新倒计时显示 + hours = int(remaining_seconds // 3600) + minutes = int((remaining_seconds % 3600) // 60) + seconds = int(remaining_seconds % 60) + + countdown_text = f"{hours:02d}:{minutes:02d}:{seconds:02d}" + self.countdown_var.set(countdown_text) + + # 等待1秒 + time.sleep(1) + remaining_seconds -= 1 + + if self.is_running and remaining_seconds <= 0: + # 时间到,执行关机命令 + self.execute_shutdown() + + def execute_shutdown(self): + # 执行Windows关机命令(立即关机,无等待时间) + try: + # 使用/s参数表示关机,/t 0表示立即执行,/f强制关闭所有应用程序 + os.system("shutdown /s /f /t 0") + self.status_var.set("正在关机...") + except Exception as e: + messagebox.showerror("错误", f"关机命令执行失败: {str(e)}") + self.cancel_shutdown_timer() + + +def main(): + root = tk.Tk() + app = ShutdownTimerApp(root) + root.mainloop() + + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..241259f --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +pyinstaller \ No newline at end of file