feat: 初始化项目
This commit is contained in:
commit
fed6c361a5
|
|
@ -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
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
3.13.0
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
## 打包
|
||||||
|
|
||||||
|
在 windows 中打开 powersehll 执行下面命令
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# 安装依赖
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
# 打包
|
||||||
|
python3 -m PyInstaller --onefile --windowed --icon=app.ico --name=ShutdownTimer 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()
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
pyinstaller
|
||||||
Loading…
Reference in New Issue