赞
踩
本程序类似于按键精灵,代替用户执行重复性的的按键、输入文本、鼠标点击功能,可设置时间延迟。
示例如图:
使用流程:
1.共有ABCDEF六套方案,用户编辑任意方案
2.点击打开,可打开之前保存的方案
点击保存,可保存方案。
点击生成之后将不可编辑,并且开始监听热键,启动热键执行方案,结束热键均为F12
点击修改之后可以修改,结束监听按键,按键将无法执行,修改完成点击生成
3.按键框可输入普通按键,如N,1,t等,执行时会按压此键
按键框可输入文本,如:adsaf,123234等,执行时会输入此文本
按键框激活时,按压TAB 或者回车键,按键框会相应,,执行时照此执行
按键框激活时,在按键框以外点击鼠标左键或者右键,按键框会相应显示,执行时照此执行
延迟框可输入上次按键后需要间隔的时间,单位是秒,如:1 或者 1.3 等,输入汉字会崩溃
三个功能同时工作,互相影响,所以需要三个线程,分别是
1.主线程,ui界面需要ui.show,所以一直占用一个线程,如果其他动作时间过长,会无响应
使用qtdesigner.exe设置ui界面,然后调用,尽量多的在qtdesigner完成设置
2.监听线程,持续监听全局热键,以便控制方案的开启和关闭
使用QThread多线程, pyqtSignal线程间传输信号.
使用pyhooked import Hook, KeyboardEvent全局监听热键,本打算用PYHK,但是安装不了,听说pyhk也是有大佬打包好的,看来还有其他方法可以
3.自动化线程,收到接听到的信号之后,开始执行,自动化输入
使用pyautogui#实现自动化
- # -*- coding:utf-8 -*-
-
- import sys#读取数据文件用
- import time#控制按键的延迟
-
- import pyautogui#实现自动化
- from PyQt5.QtCore import Qt, QThread, pyqtSignal# QThread多线程, pyqtSignal线程间传输信号
- from PyQt5.QtGui import QDoubleValidator#延迟框只能输入数字
- from PyQt5.QtWidgets import QApplication, QMainWindow
- from PyQt5 import sip#打包时显示WARNING: Hidden import "sip" not found!,加上也没啥用
- from pyhooked import Hook, KeyboardEvent#全局监听热键,本打算用PYHK,但是安装不了
-
- from anjian_ui_main import Ui_MainWindow # 调用qtdesigner.exe生成的主窗口,好省事
-
-
- # 子线程1_执行命令,自动化线程
- class BackendThread(QThread):
- def __init__(self, e=0):
- super().__init__()
- self.e = e # 传入的按键值,F6=0,使用方案A
- def run(self):
- while 1: # 默认一直循环
- # 执行A方案的文本框内容
- for index, step in enumerate(ui.dataALL[self.e]):
- if step: # 若不为空
- if index % 2 != 1: # 除2无余数,也是就是偶数,按键信息框
- if len(step) == 1: # 只是1个按键,那就是按键,按压它
- pyautogui.press(step)
- elif step == "左键":#那就点击左键
- pyautogui.leftClick()
- elif step == "右键":#那就是右键
- pyautogui.rightClick()
- elif step == "tab":#那就按压tab键
- print(f"输入{step}")
- pyautogui.press("tab")
- elif step == "Enter":
- pyautogui.press("Enter")
- print(f"输入{step}")
- else:
- pyautogui.write(step) # 否则就是输入文本
- print(f"输入{step}")
- else: # 是时间框体
- time.sleep(float(step))#延迟数秒
- print(f"延迟{step}秒")
- # 若是执行一次,索引为1,退出循环
- if ui.comboBoxall[self.e].currentIndex() == 0:
- print("仅执行一次")
- break
- print("再循环一次")
-
-
- # 子线程2_hotkey
- class hotkeynew(QThread):
- sinOut = pyqtSignal(int) # 监听到热键后,传出的信号
- def run(self):
- def handle_events(args):
- if isinstance(args, KeyboardEvent):
- if args.current_key == "F5" and args.event_type == "key down": # 如果F5按下了,传出0,也就是方案A
- self.sinOut.emit(0)
- if args.current_key == "F6" and args.event_type == "key down":
- self.sinOut.emit(1)
- if args.current_key == "F7" and args.event_type == "key down":
- self.sinOut.emit(2)
- if args.current_key == "F8" and args.event_type == "key down":
- self.sinOut.emit(3)
- if args.current_key == "F9" and args.event_type == "key down":
- self.sinOut.emit(4)
- if args.current_key == "F10" and args.event_type == "key down":
- self.sinOut.emit(5)
- if args.current_key == "F12" and args.event_type == "key down":# 如果F12按下了,传出12,关闭线程
- self.sinOut.emit(12)
- hk = Hook()#实例化线程
- hk.handler = handle_events
- hk.hook()#启动热键监控
-
-
- class MainWindow(QMainWindow, Ui_MainWindow): # 多重继承QMainWindow和Ui_MainWindow
-
- def __init__(self):
- super(MainWindow, self).__init__() # 先调用父类QMainWindow的初始化方法
- self.setupUi(self) # 再调用setupUi方法
-
- # 实例化热键线程
- self.treadhotkey = hotkeynew()
- self.treadhotkey.sinOut.connect(self.doit) # 热键后发送信号给执行
- # 实例化执行线程
- self.treaddoit = BackendThread()
-
- self.dataALL = [[], [], [], [], [], []] # 用来存储6种方案
- self.anjianlei = [self.anjianA, self.anjianB, self.anjianC, self.anjianD, self.anjianE, self.anjianF]
- self.deleylei = [self.deleyA, self.deleyB, self.deleyC, self.deleyD, self.deleyE, self.deleyF]
- self.comboBoxall = [self.comboBox1, self.comboBox2, self.comboBox3, self.comboBox4, self.comboBox5,
- self.comboBox6]
-
- self.saveaction.triggered.connect(self.savenow) # 保存连接到savenow
- self.openaction.triggered.connect(self.opennow) # 打开连接到opennow
- self.finishwriteaction.triggered.connect(self.finishwrite) # 生成按键连接到finishwrite
- self.rewriteaction.triggered.connect(self.rewrite) # 修改按键连接到rewrite
- #重新定义主页面的按键,去掉焦点,否则不能输入TAB。其实可以在qtdesigner.exe设置
- for u in range(6): # 6种方案
- for i in range(8): # 8个按键
- self.anjianlei[u].itemAt(i).widget().setFocusPolicy(Qt.ClickFocus) # 单击成为焦点,为了tab能用
- self.deleylei[u].itemAt(i).widget().setFocusPolicy(Qt.ClickFocus) # 单击成为焦点
- self.deleylei[u].itemAt(i).widget().setValidator(QDoubleValidator()) # 时间框体只能输入数字
-
- def savenow(self): # 保存的动作
- self.dataALL = [[], [], [], [], [], []] # 6种方案,之前的清理掉,重新保存现在的
- #现在的方案都保存进去
- for u in range(6): # 6种方案
- for i in range(8): # 8个按键
- self.dataALL[u].append(self.anjianlei[u].itemAt(i).widget().text())
- self.dataALL[u].append(self.deleylei[u].itemAt(i).widget().text())
-
-
- file = open("anjiandata.txt", "w")#打开txt。数据较少,为了方便,习惯用txt保存数据
- file.write(str(self.dataALL))#写入
- print("写入成功")
- file.close()#关闭
-
- def opennow(self): # 打开之前保存的数据
- with open("anjiandata.txt", "r") as file:
- self.dataALL = eval(file.read()) # 之前保存的数据,file.read()是str格式,需要转化为list,用eval,字典转化用ast
- #把打开的输入输入到各个文本框
- for u in range(6): # 6种方案
- for i in range(8): # 8个按键
- self.anjianlei[u].itemAt(i).widget().setText(self.dataALL[u][i * 2])
- self.deleylei[u].itemAt(i).widget().setText(self.dataALL[u][i * 2 + 1])
-
- def finishwrite(self): # 生成之后不可写
- if self.focusWidget(): # 保存以后有焦点就清除
- self.focusWidget().clearFocus()
- for u in range(6): # 6种方案
- for i in range(8): # 8个按键
- self.anjianlei[u].itemAt(i).widget().setReadOnly(1) # 设置不可写
- self.deleylei[u].itemAt(i).widget().setReadOnly(1)# 设置不可写
- self.anjianlei[u].itemAt(i).widget().setFocusPolicy(Qt.NoFocus) # 不能设为焦点
- self.deleylei[u].itemAt(i).widget().setFocusPolicy(Qt.NoFocus) # 不能设为焦点
- self.dataALL[u].append(self.anjianlei[u].itemAt(i).widget().text()) # 储存下文本
- self.dataALL[u].append(self.deleylei[u].itemAt(i).widget().text()) # 储存下文本
- print("生成之后开启监控热键线程")
- self.treadhotkey.start()#生成之后开启监控热键线程
-
- def rewrite(self): # 重写之后可以写
- for u in range(6): # 6种方案
- for i in range(8): # 8个按键
- self.anjianlei[u].itemAt(i).widget().setReadOnly(0)#设置可以写
- self.deleylei[u].itemAt(i).widget().setReadOnly(0)#设置可以写
- self.anjianlei[u].itemAt(i).widget().setFocusPolicy(Qt.ClickFocus) # 设只能单击为焦点
- self.deleylei[u].itemAt(i).widget().setFocusPolicy(Qt.ClickFocus) # 设只能单击为焦点
- # 重写之后关闭监控热键线程
-
- self.treadhotkey.terminate()
- # 如过还有执行线程,关闭他
- if self.treaddoit.isRunning():
- self.treaddoit.terminate()
- print("关闭线程")
-
- # 重写鼠标事件
- def mousePressEvent(self, event):
- if event.button() == Qt.LeftButton and self.focusWidget(): # 如果左键并且有焦点
- self.focusWidget().setText("左键")#这个框体的文本设为左键
- if event.button() == Qt.RightButton and self.focusWidget():
- self.focusWidget().setText("右键")
-
- # 执行热键的方案,重写事件
- def keyPressEvent(self, event):
- if event.key() == Qt.Key_Tab and self.focusWidget():#如果按了tab并且有焦点
- self.focusWidget().setText("tab")#这个框体的文本设为tab
- if event.key() == 16777220 and self.focusWidget(): #如果按了回车并且有焦点
- self.focusWidget().setText("Enter")
-
- def doit(self, e): # e是按键的表示,F6用6表示
- if e == 12: # 按了F12
- if self.treaddoit.isRunning():#若有线程就关闭他
- self.treaddoit.terminate()
- print("关闭线程")
- else:
- pass
- else:
- # 实例化线程
- self.treaddoit = BackendThread(e)
- self.treaddoit.start()
- print(f"启动线程{e}")
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- ui = MainWindow()
- ui.show()
- sys.exit(app.exec_())
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
附赠qtdesigner.exe生成的代码,诸君可以拿去打包,这个不需要看,打包用
- # -*- coding: utf-8 -*-
-
- # Form implementation generated from reading ui file 'anjian_ui_main.ui'
- #
- # Created by: PyQt5 UI code generator 5.15.6
- #
- # WARNING: Any manual changes made to this file will be lost when pyuic5 is
- # run again. Do not edit this file unless you know what you are doing.
-
-
- from PyQt5 import QtCore, QtGui, QtWidgets
-
-
- class Ui_MainWindow(object):
- def setupUi(self, MainWindow):
- MainWindow.setObjectName("MainWindow")
- MainWindow.resize(1298, 791)
- MainWindow.setLocale(QtCore.QLocale(QtCore.QLocale.Chinese, QtCore.QLocale.China))
- self.centralwidget = QtWidgets.QWidget(MainWindow)
- self.centralwidget.setObjectName("centralwidget")
- self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
- self.gridLayout.setObjectName("gridLayout")
- self.verticalLayoutA = QtWidgets.QVBoxLayout()
- self.verticalLayoutA.setObjectName("verticalLayoutA")
- self.label_15 = QtWidgets.QLabel(self.centralwidget)
- self.label_15.setObjectName("label_15")
- self.verticalLayoutA.addWidget(self.label_15)
- self.horizontalLayout = QtWidgets.QHBoxLayout()
- self.horizontalLayout.setObjectName("horizontalLayout")
- self.verticalLayout_19 = QtWidgets.QVBoxLayout()
- self.verticalLayout_19.setObjectName("verticalLayout_19")
- self.label = QtWidgets.QLabel(self.centralwidget)
- self.label.setObjectName("label")
- self.verticalLayout_19.addWidget(self.label)
- self.label_3 = QtWidgets.QLabel(self.centralwidget)
- self.label_3.setObjectName("label_3")
- self.verticalLayout_19.addWidget(self.label_3)
- self.label_5 = QtWidgets.QLabel(self.centralwidget)
- self.label_5.setObjectName("label_5")
- self.verticalLayout_19.addWidget(self.label_5)
- self.label_7 = QtWidgets.QLabel(self.centralwidget)
- self.label_7.setObjectName("label_7")
- self.verticalLayout_19.addWidget(self.label_7)
- self.label_9 = QtWidgets.QLabel(self.centralwidget)
- self.label_9.setObjectName("label_9")
- self.verticalLayout_19.addWidget(self.label_9)
- self.label_18 = QtWidgets.QLabel(self.centralwidget)
- self.label_18.setObjectName("label_18")
- self.verticalLayout_19.addWidget(self.label_18)
- self.label_17 = QtWidgets.QLabel(self.centralwidget)
- self.label_17.setObjectName("label_17")
- self.verticalLayout_19.addWidget(self.label_17)
- self.label_21 = QtWidgets.QLabel(self.centralwidget)
- self.label_21.setObjectName("label_21")
- self.verticalLayout_19.addWidget(self.label_21)
- self.horizontalLayout.addLayout(self.verticalLayout_19)
- self.anjianA = QtWidgets.QVBoxLayout()
- self.anjianA.setObjectName("anjianA")
- self.anjianA1 = QtWidgets.QLineEdit(self.centralwidget)
- self.anjianA1.setText("")
- self.anjianA1.setObjectName("anjianA1")
- self.anjianA.addWidget(self.anjianA1)
- self.anjianA2 = QtWidgets.QLineEdit(self.centralwidget)
- self.anjianA2.setObjectName("anjianA2")
- self.anjianA.addWidget(self.anjianA2)
- self.anjianA3 = QtWidgets.QLineEdit(self.centralwidget)
- self.anjianA3.setObjectName("anjianA3")
- self.anjianA.addWidget(self.anjianA3)
- self.anjianA4 = QtWidgets.QLineEdit(self.centralwidget)
- self.anjianA4.setObjectName("anjianA4")
- self.anjianA.addWidget(self.anjianA4)
- self.anjianA5 = QtWidgets.QLineEdit(self.centralwidget)
- self.anjianA5.setObjectName("anjianA5")
- self.anjianA.addWidget(self.anjianA5)
- self.anjianA6 = QtWidgets.QLineEdit(self.centralwidget)
- self.anjianA6.setObject
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。