from
PyQt5
import
QtWidgets, uic, QtCore
from
pynput
import
keyboard, mouse
import
pygetwindow as gw
from
PyQt5.QtGui
import
QPainter, QColor, QCursor
from
PyQt5.QtCore
import
Qt, QRectF
from
pynput.mouse
import
Button, Controller
import
pyautogui
import
threading
import
time
import
os
ui_path
=
os.path.join(os.path.dirname(os.path.abspath(__file__)),
'form.ui'
)
key_time_dict
=
{}
window
=
None
controller
=
None
mouseX
=
0
mouseY
=
0
class
MyLineEdit(QtWidgets.QLineEdit):
def
mousePressEvent(
self
, event):
super
(MyLineEdit,
self
).mousePressEvent(event)
print
(f
'----------------Mouse left button pressed: {event.text()}'
)
def
keyPressEvent(
self
, event):
super
(MyLineEdit,
self
).keyPressEvent(event)
key
=
event.key()
print
(f
'------------------Key pressed: {key}'
)
key_char
=
event.text()
print
(f
'-----------------Pressed key char: {key_char}'
)
class
ToggleButton(QtWidgets.QPushButton):
def
__init__(
self
, parent
=
None
):
super
(ToggleButton,
self
).__init__(parent)
self
.setCheckable(
True
)
self
.setMinimumWidth(
66
)
self
.setMinimumHeight(
28
)
def
paintEvent(
self
, event):
label
=
"ON"
if
self
.isChecked()
else
"OFF"
bg_color
=
QColor(
0
,
155
,
0
)
if
self
.isChecked()
else
QColor(
155
,
155
,
155
)
radius
=
10
width
=
28
center
=
self
.rect().center()
painter
=
QPainter(
self
)
painter.setRenderHint(QPainter.Antialiasing)
painter.translate(center)
painter.setBrush(QColor(
255
,
255
,
255
))
pen
=
painter.pen()
pen.setWidth(
2
)
pen.setColor(QColor(
155
,
155
,
155
))
painter.setPen(pen)
painter.drawRoundedRect(QRectF(
-
width,
-
radius,
2
*
width,
2
*
radius), radius, radius)
painter.setBrush(QColor(bg_color))
sw_rect
=
QRectF(
-
radius,
-
radius, width,
2
*
radius)
if
not
self
.isChecked():
sw_rect.moveLeft(
-
width)
else
:
sw_rect.moveRight(width)
painter.drawRoundedRect(sw_rect, radius, radius)
painter.setBrush(QColor(
255
,
255
,
255
))
painter.drawText(sw_rect, Qt.AlignCenter, label)
class
Ui(QtWidgets.QMainWindow):
def
__init__(
self
):
super
(Ui,
self
).__init__()
uic.loadUi(ui_path,
self
)
self
.button
=
self
.findChild(QtWidgets.QPushButton,
'Add'
)
self
.button.clicked.connect(
self
.buttonClicked)
self
.line_edit
=
self
.findChild(QtWidgets.QLineEdit,
'lineName'
)
self
.spin_box
=
self
.findChild(QtWidgets.QDoubleSpinBox,
'doubleSpinBox'
)
self
.list_widget
=
self
.findChild(QtWidgets.QListWidget,
'listWidget'
)
self
.statusButton
=
self
.findChild(QtWidgets.QPushButton,
'statusButton'
)
tmpParent
=
self
.statusButton.parent()
tmpGeometry
=
self
.statusButton.geometry()
self
.statusButton.setParent(
None
)
self
.statusButton
=
ToggleButton(
self
)
self
.statusButton.setGeometry(tmpGeometry)
self
.statusButton.clicked.connect(
lambda
:
self
.statusButtonClicked(keyboard.Key.f1))
self
.statusButton.toggled.connect(
lambda
:
print
(f
"Toggle button state: {self.statusButton.isChecked()}"
))
self
.xPos
=
self
.findChild(QtWidgets.QLineEdit,
'xPos'
)
self
.yPos
=
self
.findChild(QtWidgets.QLineEdit,
'yPos'
)
self
.mouseDelay
=
self
.findChild(QtWidgets.QDoubleSpinBox,
'mouseDelay'
)
self
.mouseStatusButton
=
self
.findChild(QtWidgets.QPushButton,
'mouseStatusButton'
)
tmpParent
=
self
.mouseStatusButton.parent()
tmpGeometry
=
self
.mouseStatusButton.geometry()
self
.mouseStatusButton.setParent(
None
)
self
.mouseStatusButton
=
ToggleButton(
self
)
self
.mouseStatusButton.setGeometry(tmpGeometry)
self
.mouseStatusButton.toggled.connect(
lambda
:
print
(f
"Toggle mouseStatusButton state: {self.mouseStatusButton.isChecked()}"
))
self
.buttonAddMap
=
self
.findChild(QtWidgets.QPushButton,
'AddMap'
)
self
.buttonAddMap.clicked.connect(
self
.addMapButtonClicked)
self
.fromKey
=
self
.findChild(QtWidgets.QLineEdit,
'fromKey'
)
self
.toKey
=
self
.findChild(QtWidgets.QLineEdit,
'toKey'
)
tmpLineEditParent
=
self
.fromKey.parent()
tmpLineEditGeometry
=
self
.fromKey.geometry()
self
.fromKey.setParent(
None
)
self
.fromKey
=
MyLineEdit(
self
)
self
.fromKey.setGeometry(tmpLineEditGeometry)
self
.mapStatusButton
=
self
.findChild(QtWidgets.QPushButton,
'mapStatusButton'
)
tmpParent
=
self
.mapStatusButton.parent()
tmpGeometry
=
self
.mapStatusButton.geometry()
self
.mapStatusButton.setParent(
None
)
self
.mapStatusButton
=
ToggleButton(
self
)
self
.mapStatusButton.setGeometry(tmpGeometry)
self
.mapStatusButton.clicked.connect(
lambda
:
self
.statusButtonClicked(keyboard.Key.f4))
self
.mapStatusButton.toggled.connect(
lambda
:
print
(f
"Toggle mapStatusButton state: {self.mapStatusButton.isChecked()}"
))
self
.show()
def
buttonClicked(
self
):
try
:
key
=
self
.line_edit.text()
time
=
self
.spin_box.value()
if
key
in
key_time_dict
or
key
not
in
pyautogui.KEYBOARD_KEYS:
return
key_time_dict[key]
=
time
self
.list_widget.addItem(f
'Key: {key} : Sec: {time}'
)
except
Exception as e:
print
(e)
def
addMapButtonClicked(
self
):
try
:
key
=
self
.line_edit.text()
time
=
self
.spin_box.value()
if
key
in
key_time_dict
or
key
not
in
pyautogui.KEYBOARD_KEYS:
return
key_time_dict[key]
=
time
self
.list_widget.addItem(f
'Key: {key} : Sec: {time}'
)
except
Exception as e:
print
(e)
def
statusButtonClicked(
self
, key):
print
(
"statusButtonClicked"
)
try
:
controller.on_press(key)
except
Exception as e:
print
(e)
def
contextMenuEvent(
self
, event):
try
:
widget
=
self
.childAt(event.pos())
if
widget
=
=
self
.list_widget
or
widget.parent()
=
=
self
.list_widget:
contextMenu
=
QtWidgets.QMenu(
self
)
delAction
=
contextMenu.addAction(
"Delete"
)
action
=
contextMenu.exec_(
self
.mapToGlobal(event.pos()))
if
action
=
=
delAction:
current_item
=
self
.list_widget.currentItem()
if
current_item:
row
=
self
.list_widget.row(current_item)
self
.list_widget.takeItem(row)
del
key_time_dict[current_item.text().split(
":"
)[
1
].strip()]
else
:
print
(
"No widget found"
)
except
Exception as e:
print
(e)
class
Controller:
MOUSE_STATUS_CLICK
=
0
MOUSE_STATUS_PRESS
=
1
def
__init__(
self
):
self
.mouse_controller
=
mouse.Controller()
self
.mouse_pressed
=
False
self
.keyboard_stop_flag
=
True
self
.mouse_auto_stop_flag
=
True
def
on_press(
self
, key):
try
:
if
key
=
=
keyboard.Key.f1:
if
self
.keyboard_stop_flag:
self
.keyboard_stop_flag
=
False
window.statusButton.setChecked(
True
)
self
.start_keyboard_press_key()
else
:
self
.keyboard_stop_flag
=
True
window.statusButton.setChecked(
False
)
elif
key
=
=
keyboard.Key.f2:
if
self
.mouse_auto_stop_flag:
self
.mouse_auto_stop_flag
=
False
window.mouseStatusButton.setChecked(
True
)
self
.start_mouse_auto_click_key(
self
.MOUSE_STATUS_CLICK)
else
:
self
.mouse_auto_stop_flag
=
True
window.mouseStatusButton.setChecked(
False
)
elif
key
=
=
keyboard.Key.f3:
if
self
.mouse_auto_stop_flag:
self
.mouse_auto_stop_flag
=
False
window.mouseStatusButton.setChecked(
True
)
self
.start_mouse_auto_click_key(
self
.MOUSE_STATUS_PRESS)
else
:
self
.mouse_auto_stop_flag
=
True
window.mouseStatusButton.setChecked(
False
)
elif
key
=
=
keyboard.Key.f4:
pass
elif
key
=
=
keyboard.Key.f12:
mouse_pos
=
QCursor.pos()
global
mouseX, mouseY
mouseX
=
mouse_pos.x()
mouseY
=
mouse_pos.y()
window.xPos.setText(
str
(mouseX))
window.yPos.setText(
str
(mouseY))
else
:
print
(f
"{key} pressed"
)
except
Exception as e:
import
traceback
traceback.print_exc()
def
on_release(
self
, key):
if
key
=
=
keyboard.Key.esc:
return
False
def
on_mouse_press(
self
, x, y, button, pressed):
if
pressed:
print
(f
'鼠标按键{button}被按下,位置在({x}, {y})'
)
def
on_mouse_release(
self
, x, y, button, pressed):
if
not
pressed:
print
(f
'鼠标按键{button}被释放,位置在({x}, {y})'
)
def
start_keyboard_press_key(
self
):
for
key, interval
in
key_time_dict.items():
if
key
in
pyautogui.KEYBOARD_KEYS:
print
(
"启动线程, 按键: "
, key,
" 间隔: "
, interval)
t
=
threading.Thread(target
=
self
.press_key, args
=
(key, interval))
t.daemon
=
True
t.start()
else
:
print
(f
"Key: {key} is not a valid key"
)
def
press_key(
self
, key, interval):
print
(
"按键: "
, key,
" 间隔: "
, interval)
while
True
:
if
self
.keyboard_stop_flag:
break
pyautogui.press(key)
time.sleep(interval)
def
start_mouse_auto_click_key(
self
, status):
print
(
"启动鼠标自动点击线程... "
)
if
status
=
=
self
.MOUSE_STATUS_CLICK:
print
(f
"鼠标自动点击... delay:{window.mouseDelay.value()}"
)
delay
=
window.mouseDelay.value()
t
=
threading.Thread(target
=
self
.mouse_click, args
=
(delay,))
t.daemon
=
True
t.start()
elif
status
=
=
self
.MOUSE_STATUS_PRESS:
print
(
"鼠标长按... "
)
mouseC
=
mouse.Controller()
mouseC
pyautogui.mouseDown()
t
=
threading.Thread(target
=
self
.mouse_press)
t.daemon
=
True
t.start()
def
mouse_click(
self
, interval):
print
(
"鼠标自动点击, 间隔: "
, interval)
while
True
:
if
self
.mouse_auto_stop_flag:
break
print
(
"指定的坐标... {}, {}"
.
format
(mouseX, mouseY))
if
mouseX
=
=
0
and
mouseY
=
=
0
:
mouseXx, mouseYy
=
pyautogui.position()
else
:
mouseXx
=
mouseX
mouseYy
=
mouseY
pyautogui.click(
int
(mouseXx),
int
(mouseYy))
time.sleep(interval)
def
mouse_press(
self
):
print
(
"开启鼠标长按... "
)
while
True
:
if
self
.mouse_auto_stop_flag:
pyautogui.mouseUp()
print
(
"鼠标长按结束"
)
break
print
(
"鼠标长按中... "
)
time.sleep(
0.3
)
def
start_listener():
game_title
=
"Your Game Title"
global
controller
controller
=
Controller()
print
(
"启动线程监听..."
)
daemon
=
threading.Thread(target
=
keyboard_listener, args
=
(controller,))
daemon.daemon
=
True
daemon.start()
daemon
=
threading.Thread(target
=
mouse_listener, args
=
(controller,))
daemon.daemon
=
True
daemon.start()
def
keyboard_listener(args):
print
(
"启动线程监听键盘..."
)
controller
=
args
with keyboard.Listener(
on_press
=
controller.on_press,
on_release
=
controller.on_release) as listener:
listener.join()
def
mouse_listener(args):
print
(
"启动线程监听鼠标..."
)
controller
=
args
with mouse.Listener(
on_click
=
controller.on_mouse_press,
on_release
=
controller.on_mouse_release) as listener:
listener.join()
if
__name__
=
=
"__main__"
:
app
=
QtWidgets.QApplication([])
window
=
Ui()
window.setWindowTitle(
"按键助手"
)
start_listener()
app.exec_()