python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python键盘模拟输入

Python+PyQt5开发一个智能键盘模拟输入器(附整体源码)

作者:创客白泽

在当今数字化办公时代,自动化工具已经成为提高工作效率的重要利器,今天我要向大家介绍一款基于PyQt5和pynput库开发的智能键盘模拟输入器,感兴趣的小伙伴可以了解下

概述

在当今数字化办公时代,自动化工具已经成为提高工作效率的重要利器。今天我要向大家介绍一款基于PyQt5pynput库开发的智能键盘模拟输入器——AQUA INPUT(测试可适用于学某通)。

开发背景

在日常工作和学习中,我们经常会遇到需要重复输入相同内容的场景:

传统的手工输入方式不仅效率低下,而且容易出错。AQUA INPUT应运而生,它通过模拟真实键盘输入的方式,实现了文本内容的自动化输入,大大提升了工作效率。

技术栈

功能特性

视觉设计

核心功能

功能模块图标描述技术特点
数据输入📝支持多种数据导入方式多编码文件读取、剪贴板集成
参数配置⚙️灵活的输入参数调整滑块控制、实时预览
进度监控📊实时显示执行状态多线程进度更新、统计信息
安全控制⏹️紧急停止机制线程安全中断、状态恢复

工作流程

界面展示

主界面设计

设计亮点

特色组件展示

1. 自定义标题栏

class CustomTitleBar(QWidget):
    def __init__(self, parent):
        super().__init__(parent)
        # 实现无边框窗口的自定义拖动功能

特点

2. 赛博风格控件

class CyberButton(QPushButton):
    def __init__(self, text, parent=None):
        super().__init__(text, parent)
        # 实现动态发光效果

动画效果

3. 倒计时窗口

功能

使用教程

第一步:数据准备

提示:支持多种文件编码格式(UTF-8、GBK、GB2312等)

第二步:参数配置

参数项推荐设置说明
输入速度0.05-0.1秒/字符根据目标应用程序响应速度调整
启动延迟3-5秒给予足够时间定位光标
窗口置顶✅ 开启避免窗口切换中断输入
倒计时界面✅ 开启可视化倒计时提示

第三步:执行输入

第四步:异常处理

高级技巧

代码深度解析

1. 架构设计

# 核心类关系图
classDiagram
    class MainWindow {
        -QTextEdit text_edit
        -TypeThread thread
        -QProgressBar progress_bar
        +start_typing()
        +stop_typing()
    }
    
    class TypeThread {
        -str text
        -float speed
        +run()
        +stop()
    }
    
    class CustomTitleBar {
        -QPushButton close_btn
        +mousePressEvent()
        +mouseMoveEvent()
    }
    
    MainWindow --> TypeThread
    MainWindow --> CustomTitleBar

2. 多线程输入核心

class TypeThread(QThread):
    update_signal = pyqtSignal(str)
    finished_signal = pyqtSignal()
    
    def run(self):
        keyboard = Controller()
        total_chars = len(self.text)
        
        for i, char in enumerate(self.text):
            if not self._is_running:
                break
                
            keyboard.type(char)
            progress = int((i + 1) / total_chars * 100)
            self.progress_signal.emit(progress)
            
            if self.speed > 0:
                time.sleep(self.speed)

关键技术点

3. 界面主题系统

def set_aqua_theme(self):
    """设置青色赛博朋克主题"""
    self.setStyleSheet("""
        QMainWindow {
            background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
                stop:0 #1a1a1a, stop:0.5 #2a2a2a, stop:1 #1a1a1a);
            color: #00ffff;
            border: 1px solid #00ffff;
            border-radius: 8px;
        }
    """)

样式特点

4. 资源管理机制

def get_resource_path(relative_path):
    """获取资源的绝对路径,兼容开发环境和打包后环境"""
    try:
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")
    
    # 多路径查找策略
    path = os.path.join(base_path, relative_path)
    if not os.path.exists(path):
        # 尝试在当前目录和上级目录查找
        current_dir_path = os.path.join(os.path.abspath("."), relative_path)
        if os.path.exists(current_dir_path):
            return current_dir_path
    return path

兼容性设计

5. 动画效果实现

class CyberButton(QPushButton):
    def __init__(self, text, parent=None):
        super().__init__(text, parent)
        self._glow = 0
        self.setMouseTracking(True)

    def animate_glow(self, target):
        animation = QPropertyAnimation(self, b"glow")
        animation.setDuration(300)
        animation.setStartValue(self._glow)
        animation.setEndValue(target)
        animation.setEasingCurve(QEasingCurve.OutCubic)
        animation.start()

动画技术

源码下载

import os
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, 
                            QPushButton, QLabel, QTextEdit, QWidget, QFileDialog, 
                            QMessageBox, QSpinBox, QCheckBox, QDialog, QDoubleSpinBox,
                            QGroupBox, QProgressBar, QScrollArea,QSizePolicy, QSlider)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer, QPropertyAnimation, QEasingCurve
from PyQt5.QtGui import QFont, QIcon, QPalette, QColor, QLinearGradient, QPainter
from PyQt5.QtCore import pyqtProperty
from pynput.keyboard import Controller
import time

def get_resource_path(relative_path):
    """获取资源的绝对路径,兼容开发环境和打包后环境"""
    try:
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    path = os.path.join(base_path, relative_path)
    
    # 如果找不到文件,尝试在多个位置查找
    if not os.path.exists(path):
        # 尝试在当前目录查找
        current_dir_path = os.path.join(os.path.abspath("."), relative_path)
        if os.path.exists(current_dir_path):
            return current_dir_path
        
        # 尝试在上级目录查找
        parent_dir_path = os.path.join(os.path.abspath(".."), relative_path)
        if os.path.exists(parent_dir_path):
            return parent_dir_path
    
    return path

class TitleBarButton(QPushButton):
    def __init__(self, text, parent=None):
        super().__init__(text, parent)
        self.setFixedSize(30, 25)
        self.setStyleSheet("""
            QPushButton {
                background-color: rgba(80, 80, 80, 200);
                border: 1px solid #00ffff;
                border-radius: 3px;
                color: #00ffff;
                font-size: 10px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: rgba(100, 100, 100, 200);
            }
            QPushButton:pressed {
                background-color: rgba(120, 120, 120, 200);
            }
        """)

class CloseButton(TitleBarButton):
    def __init__(self, parent=None):
        super().__init__("✕", parent)
        self.setStyleSheet("""
            QPushButton {
                background-color: rgba(80, 80, 80, 200);
                border: 1px solid #00ffff;
                border-radius: 3px;
                color: #00ffff;
                font-size: 12px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: rgba(255, 0, 0, 100);
                border: 1px solid #ff0000;
                color: #ffffff;
            }
            QPushButton:pressed {
                background-color: rgba(200, 0, 0, 150);
            }
        """)

class MinimizeButton(TitleBarButton):
    def __init__(self, parent=None):
        super().__init__("—", parent)

class MaximizeButton(TitleBarButton):
    def __init__(self, parent=None):
        super().__init__("□", parent)

class CyberLabel(QLabel):
    def __init__(self, text, parent=None):
        super().__init__(text, parent)
        self._glow_intensity = 0
        self.glow_animation = QPropertyAnimation(self, b"glow_intensity")
        self.glow_animation.setDuration(2000)
        self.glow_animation.setLoopCount(-1)
        self.glow_animation.setStartValue(0)
        self.glow_animation.setEndValue(100)
        self.glow_animation.start()

    def get_glow_intensity(self):
        return self._glow_intensity

    def set_glow_intensity(self, value):
        self._glow_intensity = value
        self.update()

    glow_intensity = pyqtProperty(int, get_glow_intensity, set_glow_intensity)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        
        # 青色主题
        gradient = QLinearGradient(0, 0, self.width(), 0)
        base_color = QColor(0, 255, 255)  # 青色
        glow_color = QColor(0, 200, 200, 150 + self._glow_intensity)
        
        gradient.setColorAt(0, base_color)
        gradient.setColorAt(0.5, glow_color)
        gradient.setColorAt(1, base_color)
        
        painter.setPen(QColor(0, 255, 255))
        painter.setFont(self.font())
        painter.drawText(self.rect(), Qt.AlignCenter, self.text())

class CyberButton(QPushButton):
    def __init__(self, text, parent=None):
        super().__init__(text, parent)
        self._glow = 0
        self.setMouseTracking(True)

    def enterEvent(self, event):
        self.animate_glow(50)
        super().enterEvent(event)

    def leaveEvent(self, event):
        self.animate_glow(0)
        super().leaveEvent(event)

    def animate_glow(self, target):
        animation = QPropertyAnimation(self, b"glow")
        animation.setDuration(300)
        animation.setStartValue(self._glow)
        animation.setEndValue(target)
        animation.setEasingCurve(QEasingCurve.OutCubic)
        animation.start()

    def get_glow(self):
        return self._glow

    def set_glow(self, value):
        self._glow = value
        self.update()

    glow = pyqtProperty(int, get_glow, set_glow)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        
        # 灰色背景,青色边框
        bg_color = QColor(60, 60, 60, 220)  # 深灰色
        painter.fillRect(self.rect(), bg_color)
        
        # 青色边框
        border_color = QColor(0, 255, 255, 60 + self._glow)
        painter.setPen(border_color)
        painter.drawRect(1, 1, self.width()-2, self.height()-2)
        
        # 青色文字
        text_color = QColor(0, 255, 255)
        painter.setPen(text_color)
        painter.setFont(self.font())
        painter.drawText(self.rect(), Qt.AlignCenter, self.text())

class CyberSpinBox(QSpinBox):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setStyleSheet("""
            QSpinBox {
                background-color: rgba(80, 80, 80, 200);
                border: 1px solid #00ffff;
                border-radius: 4px;
                color: #00ffff;
                padding: 5px;
                font-size: 12px;
                selection-background-color: #00ffff;
                selection-color: #000;
            }
            QSpinBox:focus {
                border: 1px solid #00cccc;
            }
            QSpinBox::up-button, QSpinBox::down-button {
                background-color: #00ffff;
                border: none;
                width: 15px;
                border-radius: 2px;
            }
            QSpinBox::up-button:hover, QSpinBox::down-button:hover {
                background-color: #00cccc;
            }
            QSpinBox::up-arrow, QSpinBox::down-arrow {
                width: 8px;
                height: 8px;
                color: #000;
            }
        """)

class CyberDoubleSpinBox(QDoubleSpinBox):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setStyleSheet("""
            QDoubleSpinBox {
                background-color: rgba(80, 80, 80, 200);
                border: 1px solid #00ffff;
                border-radius: 4px;
                color: #00ffff;
                padding: 5px;
                font-size: 12px;
                selection-background-color: #00ffff;
                selection-color: #000;
            }
            QDoubleSpinBox:focus {
                border: 1px solid #00cccc;
            }
            QDoubleSpinBox::up-button, QDoubleSpinBox::down-button {
                background-color: #00ffff;
                border: none;
                width: 15px;
                border-radius: 2px;
            }
            QDoubleSpinBox::up-button:hover, QDoubleSpinBox::down-button:hover {
                background-color: #00cccc;
            }
            QDoubleSpinBox::up-arrow, QDoubleSpinBox::down-arrow {
                width: 8px;
                height: 8px;
                color: #000;
            }
        """)

class CyberSlider(QSlider):
    def __init__(self, orientation=Qt.Horizontal, parent=None):
        super().__init__(orientation, parent)
        self.setStyleSheet("""
            QSlider::groove:horizontal {
                border: 1px solid #00ffff;
                height: 8px;
                background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
                    stop:0 #1a1a1a, stop:0.5 #2a2a2a, stop:1 #1a1a1a);
                border-radius: 4px;
            }
            QSlider::handle:horizontal {
                background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
                    stop:0 #00ffff, stop:0.5 #00cccc, stop:1 #00ffff);
                border: 1px solid #00ffff;
                width: 18px;
                margin: -5px 0;
                border-radius: 9px;
            }
            QSlider::handle:horizontal:hover {
                background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
                    stop:0 #00cccc, stop:0.5 #00aaaa, stop:1 #00cccc);
                border: 1px solid #00cccc;
            }
            QSlider::sub-page:horizontal {
                background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
                    stop:0 #00ffff, stop:0.5 #00cccc, stop:1 #00ffff);
                border-radius: 4px;
            }
        """)

class CountdownWindow(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("倒计时")
        self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
        self.setStyleSheet("""
            background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
                stop:0 #2a2a2a, stop:0.5 #3a3a3a, stop:1 #2a2a2a);
            border: 2px solid #00ffff;
            border-radius: 10px;
        """)
        
        layout = QVBoxLayout()
        self.countdown_label = QLabel("5")
        self.countdown_label.setAlignment(Qt.AlignCenter)
        self.countdown_label.setStyleSheet("""
            color: #00ffff;
            font-size: 72px;
            font-weight: bold;
            font-family: 'Arial';
            background: transparent;
        """)
        
        layout.addWidget(self.countdown_label)
        self.setLayout(layout)
        
        self.resize(200, 200)
        self.move_to_center()
    
    def move_to_center(self):
        screen = QApplication.primaryScreen().geometry()
        x = (screen.width() - self.width()) // 2
        y = (screen.height() - self.height()) // 2
        self.move(x, y)
    
    def update_countdown(self, seconds):
        self.countdown_label.setText(str(seconds))
        if seconds <= 0:
            self.close()

class TypeThread(QThread):
    update_signal = pyqtSignal(str)
    finished_signal = pyqtSignal()
    status_signal = pyqtSignal(str)
    progress_signal = pyqtSignal(int)

    def __init__(self, text, speed=0.05):
        super().__init__()
        self.text = text
        self.speed = speed
        self._is_running = True

    def run(self):
        keyboard = Controller()
        total_chars = len(self.text)
        
        for i, char in enumerate(self.text):
            if not self._is_running:
                break
                
            keyboard.type(char)
            progress = int((i + 1) / total_chars * 100)
            self.progress_signal.emit(progress)
            
            status_text = f"正在输入: {i+1}/{total_chars} 字符"
            self.status_signal.emit(status_text)
            
            if self.speed > 0:
                time.sleep(self.speed)
                
        self.finished_signal.emit()

    def stop(self):
        self._is_running = False

class CyberTextEdit(QTextEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setStyleSheet("""
            QTextEdit {
                background-color: rgba(80, 80, 80, 200);
                border: 2px solid #00ffff;
                border-radius: 8px;
                color: #00ffff;
                font-size: 14px;
                padding: 10px;
                selection-background-color: #00ffff;
                selection-color: #000;
            }
            QTextEdit:focus {
                border: 2px solid #00cccc;
            }
        """)

class CyberCheckBox(QCheckBox):
    def __init__(self, text, parent=None):
        super().__init__(text, parent)
        self.setStyleSheet("""
            QCheckBox {
                color: #00ffff;
                font-size: 12px;
                spacing: 5px;
            }
            QCheckBox::indicator {
                width: 15px;
                height: 15px;
                border: 1px solid #00ffff;
                background-color: rgba(80, 80, 80, 200);
            }
            QCheckBox::indicator:checked {
                background-color: #00ffff;
            }
            QCheckBox::indicator:hover {
                border: 1px solid #00cccc;
            }
        """)

项目结构

AQUA-INPUT/
├── main.py                 # 主程序文件
├── icon.ico               # 应用程序图标
├── requirements.txt       # 依赖包列表
├── README.md             # 项目说明文档
└── examples/             # 使用示例
    ├── sample_texts/     # 示例文本
    └── config_examples/  # 配置示例

环境要求

# Python 3.7+
pip install PyQt5==5.15.7
pip install pynput==1.7.6

快速开始

克隆代码

git clone https://gitee.com/your-repo/aqua-input.git
cd aqua-input

安装依赖

pip install -r requirements.txt

运行程序

python main.py

打包发布

# 使用PyInstaller打包
pyinstaller --onefile --windowed --icon=icon.ico --name="AQUA_INPUT" main.py

总结与展望

技术总结

AQUA INPUT项目展示了多个重要的软件开发技术:

实际应用价值

未来扩展方向

扩展功能规划

到此这篇关于Python+PyQt5开发一个智能键盘模拟输入器(附整体源码)的文章就介绍到这了,更多相关Python键盘模拟输入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文