feat: 初始化项目

This commit is contained in:
李如威 2025-10-22 10:50:00 +08:00
commit fed6c361a5
6 changed files with 251 additions and 0 deletions

91
.gitignore vendored Normal file
View File

@ -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

1
.python-version Normal file
View File

@ -0,0 +1 @@
3.13.0

11
README.md Normal file
View File

@ -0,0 +1,11 @@
## 打包
在 windows 中打开 powersehll 执行下面命令
```shell
# 安装依赖
pip3 install -r requirements.txt
# 打包
python3 -m PyInstaller --onefile --windowed --icon=app.ico --name=ShutdownTimer app.py
```

BIN
app.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

147
app.py Normal file
View File

@ -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()

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
pyinstaller