#!/usr/bin/env python3 ############################################################### # 版本:1.8.0 # 更新时间:2022年07月26日 # Need: unix, python3-tk, python3-pip, pymouse, keyboard ############################################################### import os import sys import time import json import shutil import keyboard import traceback import ttkthemes import pyautogui import threading import updatekiller import tkinter as tk import tkinter.ttk as ttk import tkinter.messagebox as messagebox import tkinter.filedialog as filedialog ######################## # ######################## def Inputt(key): if key.event_type == "up": global setting if setting: Setting(key) else: Mouse(key) def Open(): path = filedialog.askopenfilename(title="打开", filetypes=[["json 文件", "*.json"], ["全部文件", ["*.*"]]]) if not path == "" or path == (): shutil.copy(path, get_home() + "/.config/uengine-keyboard/key.json") if messagebox.askyesno(title="提示", message="导入成功!是否现在重启程序以便生效?"): ReStartProgram() def Save(): path = filedialog.asksaveasfilename(title="打开", filetypes=[["json 文件", "*.json"], ["全部文件", ["*.*"]]]) if not path == "" or path == (): shutil.copy(get_home() + "/.config/uengine-keyboard/key.json", path) messagebox.showinfo(title="提示", message="导出成功!") # 重启本应用程序 def ReStartProgram()->"重启本应用程序": python = sys.executable os.execl(python, python, * sys.argv) def Mouse(key): print(keybo) if keybo.__contains__(key.name): print(keybo[key.name]["MousePlace"]) pyautogui.FAILSAFE = False try: print((keybo[key.name]["MousePlace"][0], keybo[key.name]["MousePlace"][1])) pyautogui.click(keybo[key.name]["MousePlace"][0], keybo[key.name]["MousePlace"][1]) except: traceback.print_exc() def Setting(key): if key.event_type == 'up': keybo[key.name] = {"Mouse": "Left", "MousePlace": pyautogui.position()} write_txt("{}/.config/uengine-keyboard/key.json".format(get_home()), json.dumps(keybo)) global inputs inputs = True global setting setting = False return False def ShowTips(): global close try: if setting: settingLabelText.set('''设置方法:把鼠标移动带所需位置然后按下需要设置的按键即可({}x{}) 提示: 1、目前不支持同时按两个及以上按键,只支持在单一时间内按一个按键; 2、使用映射不能关闭本窗口,但可以最小化; 3、本程序需要 root 权限才能使用; 4、映射时会占用鼠标,所以在使用时最好不要使用鼠标;'''.format(pyautogui.position()[0], pyautogui.position()[1])) settingButton.configure(state=tk.DISABLED) else: settingLabelText.set('''点击“设置”按钮设置映射({}x{}) 提示: 1、目前不支持同时按两个及以上按键,只支持在单一时间内按一个按键; 2、使用映射不能关闭本窗口,但可以最小化; 3、本程序需要 root 权限才能使用; 4、映射时会占用鼠标,所以在使用时最好不要使用鼠标;'''.format(pyautogui.position()[0], pyautogui.position()[1])) settingButton.configure(state=tk.NORMAL) time.sleep(0.1) if not close: ShowTips() except: traceback.print_exc() print(close) if not close: ShowTips() def Closing(): global close close = True # 偷懒了,直接强制关闭进程 os.system(f"kill {os.getpid()}") def Key(): keyboard.hook(Inputt) # 获取用户主目录 def get_home()->"获取用户主目录": return os.path.expanduser('~') # 写入文本文档 def write_txt(path: "路径", things: "内容")->"写入文本文档": file = open(path, 'w', encoding='UTF-8') # 设置文件对象 file.write(things) # 写入文本 file.close() # 关闭文本对象 # 读取文本文档 def readtxt(path: "路径")->"读取文本文档": f = open(path, "r") # 设置文件对象 str = f.read() # 获取内容 f.close() # 关闭文本对象 return str # 返回结果 def Settings(): global setting setting = True def Clean(): if messagebox.askokcancel(title="提示", message="你确定要删除吗?"): shutil.rmtree("{}/.config/uengine-keyboard".format(get_home())) if messagebox.askyesno(title="提示", message="删除成功!是否现在重启程序以便生效?"): ReStartProgram() def About(): threading.Thread(target=os.system, args=["{}/uengine-runner-about".format(programPath)]).start() lock = False def ThreadCheck(): global lock lock = True pyautogui.position() lock = False def RestartProgramTimer(): threading.Thread(target=ThreadCheck).start() time.sleep(0.1) if lock: ReStartProgram() RestartProgramTimer() ################### # ################### if not os.path.exists("{}/.config/uengine-keyboard".format(get_home())): os.mkdir("{}/.config/uengine-keyboard".format(get_home())) if not os.path.exists("{}/.config/uengine-keyboard/key.json".format(get_home())): write_txt("{}/.config/uengine-keyboard/key.json".format(get_home()), "{}") ################### # ################### setting = False close = False programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string iconPath = "{}/icon.png".format(os.path.split(os.path.realpath(__file__))[0]) keybo = json.loads(readtxt("{}/.config/uengine-keyboard/key.json".format(get_home()))) version = json.loads(readtxt("{}/information.json".format(programPath)))["Version"] pyautogui.PAUSE = 0 ################### # 判断是不是 root ################### if os.geteuid() != 0: print("不是以 root 权限运行本程序!") root = tk.Tk() root.overrideredirect(1) root.withdraw() messagebox.showerror(title="错误", message="不是以 root 权限运行本程序!") sys.exit(1) ################### # ################### window = tk.Tk() win = ttk.Frame(window) show = ttk.Frame(win) settingLabelText = tk.StringVar() # 设置菜单栏 menu = tk.Menu(window, tearoff=0, background="white") programMenu = tk.Menu(menu, tearoff=0, background="white") aboutMenu = tk.Menu(menu, tearoff=0, background="white") settingLabel = ttk.Label(win, textvariable=settingLabelText) settingMouseToKeyboard = ttk.Button(show, text="启动键盘映射(已启用)") settingButton = ttk.Button(show, text="添加或覆盖键盘映射设置", command=Settings) settingMouseToKeyboard.configure(state=tk.DISABLED) style = ttkthemes.ThemedStyle(window) style.set_theme("breeze") window.protocol('WM_DELETE_WINDOW', Closing) window.resizable(0, 0) window.iconphoto(False, tk.PhotoImage(file=iconPath)) window.title("UEngine 键盘映射 {}".format(version)) menu.add_cascade(label="程序", menu=programMenu) menu.add_cascade(label="帮助", menu=aboutMenu) menu.configure(activebackground="dodgerblue") programMenu.add_command(label="导入映射设置", command=Open) programMenu.add_command(label="导出映射设置", command=Save) programMenu.add_command(label="删除所有映射设置", command=Clean) programMenu.add_separator() programMenu.add_command(label="退出程序", command=sys.exit) programMenu.configure(activebackground="dodgerblue") aboutMenu.add_command(label="关于", command=About) window.config(menu=menu) # 显示菜单栏 show.grid(row=1, column=0) settingLabel.grid(row=0, column=0) settingMouseToKeyboard.grid(row=0, column=0) settingButton.grid(row=0, column=1) win.pack(fill="both", expand="yes") keys = threading.Thread(target=Key) keys.start() threading.Thread(target=ShowTips).start() pyautogui.FAILSAFE = False threading.Thread(target=RestartProgramTimer).start() window.mainloop()