'''
注意事项:
程序会自动保存设置到 rename_settings.json 文件中,下次启动时会加载之前的设置。
-
程序需要相应的权限来模拟键盘输入
-
在其他Linux系统上可能需要安装额外的依赖:
sudo apt-get install python3-tk python3-dev
sudo apt-get install xclip xsel
-
某些Linux桌面环境可能需要配置权限才能进行全局热键监听
-
自定义按键时,请使用pyautogui支持的按键名称(如:'f2', 'right', 'enter', 'a', 'b'等)
描述:一个统信linux中运行的一个名叫重命名的python程序,通过tktinter输入参数,界面尺寸300*250,底色淡黄色,一键处理的按键是糖果绿色,字体:fangsong ti,字号12号。
程序开始运行时,等待Ctrl+B为触发功能,执行以下命令,执行完毕后自动进入下一次等待触发。具体是打开资源管理器触发功能后,自动将选中的文件通过该F2进入改名状态
功能1:输入每组连点的间隔,默认值1s,输入默认连点次数,默认1次。
功能2:输入连点键输入框,通过输入按键代码及间隔时间,实现一组连续输入。默认是:执行"F2",然后间隔0.5秒,然后执行"向右方健健"。注意,这三步就是一组连续输入。注意,也可选择改为其他键盘按键连点。
功能3:可以点击浅绿开始键,则也能开始连点,点击浅红结束键,则自动结束连点。
'''
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import tkinter as tk
from tkinter import ttk, messagebox
import time
import threading
import subprocess
import sys
import os
from pynput import keyboard
import pyautogui
import json
class RenameAssistant:
def __init__(self, root):
self.root = root
self.root.title("重命名助手")
self.root.geometry("450x300")
self.root.configure(bg='#FFFFE0') # 淡黄色背景
self.root.resizable(False, False)
# 监听状态
self.listening = False
self.running = False
self.hotkey_listener = None
# 默认设置
self.default_settings = {
'interval': 1.0,
'repeat_count': 1,
'sequence': [
{'key': 'f2', 'interval': 0.5},
{'key': 'right', 'interval': 0.1}
]
}
# 加载设置
self.settings = self.load_settings()
# 设置字体
self.font = ('Fangsong Ti', 12)
self.setup_ui()
self.start_hotkey_listener()
# 窗口关闭时清理
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
def setup_ui(self):
# 主框架
main_frame = tk.Frame(self.root, bg='#FFFFE0')
main_frame.pack(fill='both', expand=True, padx=10, pady=10)
# 功能1:间隔时间和重复次数
frame1 = tk.Frame(main_frame, bg='#FFFFE0')
frame1.pack(fill='x', pady=5)
tk.Label(frame1, text="间隔时间(秒):", bg='#FFFFE0', font=self.font).pack(side='left')
self.interval_var = tk.StringVar(value=str(self.settings['interval']))
interval_entry = tk.Entry(frame1, textvariable=self.interval_var, width=10, font=self.font)
interval_entry.pack(side='left', padx=5)
tk.Label(frame1, text="重复次数:", bg='#FFFFE0', font=self.font).pack(side='left', padx=(10, 0))
self.repeat_var = tk.StringVar(value=str(self.settings['repeat_count']))
repeat_entry = tk.Entry(frame1, textvariable=self.repeat_var, width=10, font=self.font)
repeat_entry.pack(side='left', padx=5)
# 功能2:按键序列设置
frame2 = tk.Frame(main_frame, bg='#FFFFE0')
frame2.pack(fill='x', pady=5)
tk.Label(frame2, text="按键序列:", bg='#FFFFE0', font=self.font).pack(anchor='w')
# 创建按键序列显示区域
self.sequence_frame = tk.Frame(frame2, bg='#FFFFE0')
self.sequence_frame.pack(fill='x', pady=5)
self.update_sequence_display()
# 添加新按键按钮
add_btn = tk.Button(frame2, text="添加按键", command=self.add_key_sequence,
bg='#E0E0E0', font=self.font)
add_btn.pack(side='left', padx=2)
# 重置按钮
reset_btn = tk.Button(frame2, text="重置默认", command=self.reset_to_default,
bg='#E0E0E0', font=self.font)
reset_btn.pack(side='left', padx=2)
# 保存设置按钮
save_btn = tk.Button(frame2, text="保存设置", command=self.save_settings,
bg='#E0E0E0', font=self.font)
save_btn.pack(side='left', padx=2)
# 功能3:控制按钮
frame3 = tk.Frame(main_frame, bg='#FFFFE0')
frame3.pack(fill='x', pady=10)
# 糖果绿色开始按钮
self.start_btn = tk.Button(frame3, text="开始执行", command=self.start_execution,
bg='#98FB98', fg='black', font=self.font,
activebackground='#7CFC00', width=10)
self.start_btn.pack(side='left', padx=10)
# 浅红色结束按钮
self.stop_btn = tk.Button(frame3, text="结束执行", command=self.stop_execution,
bg='#FFB6C1', fg='black', font=self.font,
activebackground='#FF69B4', width=10)
self.stop_btn.pack(side='left', padx=10)
# 状态标签
self.status_label = tk.Label(main_frame, text="状态: 等待Ctrl+B触发",
bg='#FFFFE0', font=self.font)
self.status_label.pack(pady=5)
# 监听状态标签
self.hotkey_status = tk.Label(main_frame, text="热键监听: 运行中",
bg='#FFFFE0', font=('Fangsong Ti', 10))
self.hotkey_status.pack()
def update_sequence_display(self):
# 清空现有显示
for widget in self.sequence_frame.winfo_children():
widget.destroy()
# 显示当前序列
for i, step in enumerate(self.settings['sequence']):
step_frame = tk.Frame(self.sequence_frame, bg='#FFFFE0')
step_frame.pack(fill='x', pady=2)
tk.Label(step_frame, text=f"步骤{i + 1}:", bg='#FFFFE0',
font=('Fangsong Ti', 10)).pack(side='left')
tk.Label(step_frame, text=f"按键: {step['key']}", bg='#FFFFE0',
font=('Fangsong Ti', 10)).pack(side='left', padx=5)
tk.Label(step_frame, text=f"间隔: {step['interval']}秒", bg='#FFFFE0',
font=('Fangsong Ti', 10)).pack(side='left', padx=5)
# 删除按钮
del_btn = tk.Button(step_frame, text="X", command=lambda idx=i: self.remove_step(idx),
bg='#FF9999', font=('Fangsong Ti', 8), width=2)
del_btn.pack(side='right')
def add_key_sequence(self):
# 创建添加按键的对话框
dialog = tk.Toplevel(self.root)
dialog.title("添加按键步骤")
dialog.geometry("300x150")
dialog.configure(bg='#FFFFE0')
dialog.resizable(False, False)
tk.Label(dialog, text="按键代码:", bg='#FFFFE0', font=self.font).pack(pady=5)
key_var = tk.StringVar()
key_entry = tk.Entry(dialog, textvariable=key_var, font=self.font, width=20)
key_entry.pack(pady=5)
key_entry.insert(0, "f2")
tk.Label(dialog, text="间隔时间(秒):", bg='#FFFFE0', font=self.font).pack(pady=5)
interval_var = tk.StringVar(value="0.5")
interval_entry = tk.Entry(dialog, textvariable=interval_var, font=self.font, width=10)
interval_entry.pack(pady=5)
def save_step():
key = key_var.get().strip().lower()
try:
interval = float(interval_var.get())
if interval < 0.1:
interval = 0.1
except:
interval = 0.5
self.settings['sequence'].append({'key': key, 'interval': interval})
self.update_sequence_display()
dialog.destroy()
tk.Button(dialog, text="添加", command=save_step, bg='#98FB98',
font=self.font).pack(pady=10)
def remove_step(self, index):
if 0 <= index < len(self.settings['sequence']):
self.settings['sequence'].pop(index)
self.update_sequence_display()
def reset_to_default(self):
self.settings = self.default_settings.copy()
self.interval_var.set(str(self.settings['interval']))
self.repeat_var.set(str(self.settings['repeat_count']))
self.update_sequence_display()
messagebox.showinfo("重置", "已恢复默认设置")
def save_settings(self):
try:
# 更新当前设置
self.settings['interval'] = float(self.interval_var.get())
self.settings['repeat_count'] = int(self.repeat_var.get())
# 保存到文件
with open('rename_settings.json', 'w') as f:
json.dump(self.settings, f, indent=2)
messagebox.showinfo("保存成功", "设置已保存到文件")
except Exception as e:
messagebox.showerror("保存失败", f"保存设置时出错: {str(e)}")
def load_settings(self):
try:
if os.path.exists('rename_settings.json'):
with open('rename_settings.json', 'r') as f:
return json.load(f)
except:
pass
return self.default_settings.copy()
def start_hotkey_listener(self):
"""启动热键监听"""
self.listening = True
self.hotkey_listener = keyboard.GlobalHotKeys({
'<ctrl>+b': self.trigger_hotkey
})
self.hotkey_listener.start()
def trigger_hotkey(self):
"""热键触发时的处理"""
if not self.running:
self.root.after(0, self._execute_rename_sequence)
def _execute_rename_sequence(self):
"""执行重命名序列"""
try:
self.running = True
self.status_label.config(text="状态: 执行中...")
self.start_btn.config(state='disabled')
# 获取当前设置
interval = float(self.interval_var.get())
repeat_count = int(self.repeat_var.get())
# 获取当前选中的文件(通过模拟F2)
# 首先模拟F2进入重命名模式
time.sleep(0.1) # 短暂延迟
# 执行按键序列指定次数
for _ in range(repeat_count):
for step in self.settings['sequence']:
key = step['key']
# 处理特殊按键
if key == 'right':
pyautogui.press('right')
elif key == 'left':
pyautogui.press('left')
elif key == 'enter':
pyautogui.press('enter')
elif key == 'esc':
pyautogui.press('esc')
else:
pyautogui.press(key)
# 等待指定的间隔时间
time.sleep(step['interval'])
# 每组之间的间隔
if _ < repeat_count - 1:
time.sleep(interval)
except Exception as e:
messagebox.showerror("执行错误", f"执行过程中出错: {str(e)}")
finally:
self.running = False
self.status_label.config(text="状态: 等待Ctrl+B触发")
self.start_btn.config(state='normal')
def start_execution(self):
"""手动开始执行"""
if not self.running:
threading.Thread(target=self._execute_rename_sequence, daemon=True).start()
def stop_execution(self):
"""停止执行"""
# 对于这种简单模拟,我们只能标记停止状态
# 实际执行会在当前循环结束后停止
if self.running:
self.running = False
self.status_label.config(text="状态: 正在停止...")
def on_closing(self):
"""关闭窗口时的清理"""
if self.hotkey_listener:
self.hotkey_listener.stop()
self.root.destroy()
def main():
root = tk.Tk()
app = RenameAssistant(root)
root.mainloop()
if __name__ == "__main__":
# 检查依赖
try:
import pyautogui
from pynput import keyboard
except ImportError:
print("请先安装必要的依赖库:")
print("pip install pyautogui pynput")
sys.exit(1)
main()