当我们日常使用电脑时,经常会遇到各种程序和脚本文件需要快速启动的场景。你是否也曾想过,拥有一个可以一键启动常用程序的工具呢?今天,我们将通过Python和Tkinter库创建一个个性化的程序启动器。这个启动器不仅可以在网格中添加常用的.exe或.bat文件,还能做到下次启动时自动保存,最重要的是,它美观且易用!
为何选择Python和Tkinter?
Python因其简洁、高效的编程风格广受欢迎,而Tkinter作为其内置的图形界面库,让我们能够轻松地创建桌面应用程序。无论你是编程新手还是经验丰富的开发者,使用Tkinter都能帮助你迅速实现想法。
项目预览:我们的目标
我们将构建一个10x20的网格界面,每个网格单元代表一个可以添加程序的按钮。当你单击一个网格时,可以选择一个程序文件添加进去;再次单击时,该程序将会直接运行。更妙的是,这些设置都会被保存下来,即使你关闭程序再打开,也不会丢失。
除此之外,我们还为每个网格添加了行号和列号,方便你快速定位和查找。
代码实现:让我们动手吧!
pyinstaller --onefile --windowed Grid_programs.py
首先,让我们看看代码是如何实现的。以下是完整的实现代码:
版本4.0
import tkinter as tk
from tkinter import filedialog
import json
import os
import subprocess
from datetime import datetime
import threading
import platform
SAVE_FILE = 'grid_programs.json'
log_filename = datetime.now().strftime('%Y-%m-%d-%H') + '.txt'
log_filepath = os.path.join(os.getcwd(), log_filename)
def tuple_to_string(programs):
return {
f"{
k[0]},{
k[1]}": v for k, v in programs.items()}
def string_to_tuple(programs):
return {
tuple(map(int, k.split(','))): v for k, v in programs.items()}
def save_programs(programs):
with open(SAVE_FILE, 'w', encoding='utf-8') as f:
json.dump(tuple_to_string(programs), f, ensure_ascii=False)
def load_programs():
if os.path.exists(SAVE_FILE):
try:
with open(SAVE_FILE, 'r', encoding='utf-8') as f:
return string_to_tuple(json.load(f))
except json.JSONDecodeError:
print("Error decoding JSON, starting with an empty grid.")
return {
}
return {
}
def log_operation(operation):
with open(log_filepath, 'a', encoding='utf-8') as log_file:
log_file.write(f"{
datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - {
operation}\n")
def execute_and_log(command):
try:
log_operation(f"Executing command: {
command}")
startupinfo = None
if platform.system() == "Windows":
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW # 隐藏黑窗口
process = subprocess.Popen(f'"{
command}"', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, startupinfo=startupinfo)
for line in iter(process.stdout.readline, ''):
log_operation(f"Output: {
line.strip()}")
process.stdout.close()
process.stderr.close()
except Exception as e:
log_operation(f"Failed to execute command: {
command}\nError: {
e}")
def handle_program(row, col):
if (row, col) in programs:
log_operation(f"Running program from Row {
row+1}, Col {
col+1}: {
programs[(row, col)]}")
threading.Thread(target=execute_and_log, args=(programs[(row, col)],)).start()
else:
file_path = filedialog.askopenfilename(filetypes=[("Executable files", "*.exe *.bat *.py *.*")])
if file_path:
programs[(row, col)] = file_path
buttons[row][col].config(text=os.path.basename(file_path))
save_programs(programs)
log_operation(f"Added program to Row {
row+1}, Col {
col+1}: {
file_path}")
threading.Thread(target=execute_and_log, args=(file_path,)).start()
def delete_program(row, col):
if (row, col) in programs:
del programs[(row, col)]
buttons[row][col].config(text='')
save_programs(programs)
log_operation(f"Deleted program from Row {
row+1}, Col {
col+1}")
def open_file_location(file_path):
try:
if platform.system() == "Windows":
normalized_path = os.path.normpath(file_path)
subprocess.Popen(f'explorer /select,"{
normalized_path}"')
elif platform.system() == "Darwin":
subprocess.Popen(["open", "-R", file_path])
elif platform.system() == "Linux":
subprocess.Popen(["xdg-open", os.path.dirname(file_path)])
else:
print("Unsupported operating system.")
except Exception as e:
log_operation(f"Failed to open file location: {
file_path}\nError: {
e}")
def show_context_menu(event, row, col):
context_menu = tk.Menu(root, tearoff=0)
if (row, col) in programs:
context_menu.add_command(label="Open File Location", command=lambda: open_file_location