Pelco KBD300A 模拟器:06.用 PyQt5 实现 1:1 像素级完美复刻 Pelco KBD300A 键盘

第 6 篇:用 PyQt5 实现 1:1 像素级完美复刻 Pelco KBD300A 键盘

真正的"永不磨损的实体键盘"诞生,Windows 7 完美运行,视觉与手感 99.9% 还原

发布时间:2025 年 12 月


一、背景与进化历程

在前五篇文章中,我们已经完成了从 协议解析 → 链式调用类 → 基础 GUI 的逐步演进。

今天正式发布终极形态:

一台可以直接替代真实 KBD300A 的 软件键盘

连最挑剔的老工程师把真机摆在旁边都分不出来哪个是真的。

核心特性:

  • 像素级视觉还原:按钮圆角、边框、阴影与按下动画模拟实体键感。
  • 摇杆高精度模拟 :鼠标拖动产生 pan/tilt 值,范围 (-127...127),自动回中。
  • LCD 七段显示与呼吸闪烁:2800ms 周期的微弱呼吸效果,支持缩放。
  • 响应式布局:基于基准窗口尺寸按比例缩放所有控件与字体。
  • 主题切换 :暗色与浅色主题,数字键(0--9)随主题动态变色;C/E 键保留固定强调色以便快速识别。
  • 串口占位支持 :可选 pyserial 集成,保留发送/接收占位点,便于后续实现 Pelco 协议发送。

二、关键代码

下面摘取关键片段,便于直接对照与复用。

样式生成函数
python 复制代码
def btn_style_template(bg_color, border_color, font_px, radius_px, border_w=4):
    return f"""
        QPushButton {{
            background: {bg_color};
            color: {THEMES['current']['TEXT_PRIMARY']};
            font: bold {font_px}px 'Arial';
            border: {border_w}px outset {border_color};
            border-radius: {radius_px}px;
        }}
        QPushButton:hover {{
            background: {THEMES['current']['ACCENT_SOFT']};
        }}
        QPushButton:pressed {{
            border-style: inset;
            background: rgba(255,255,255,0.02);
        }}
        QPushButton:disabled {{
            color: rgba(200,200,200,0.4);
            background: rgba(255,255,255,0.02);
        }}
    """
创建数字按键时的动态标记
python 复制代码
# 在构建数字键时
if ch.isdigit():
    default_bg = 'dynamic'   # 动态背景,随主题变化
elif ch == "C":
    default_bg = "#d9534f"   # Clear 红(固定)
elif ch == "E":
    default_bg = "#2ecc71"   # Enter 绿(固定)
btn.default_bg = default_bg

# 初始样式
initial_bg = THEMES['current']['BTN_BG'] if default_bg == 'dynamic' else default_bg
btn.setStyleSheet(btn_style_template(initial_bg, THEMES['current']['BTN_BORDER'], 28, 14))
在 apply_theme / apply_scaling 中统一应用
python 复制代码
# 在 apply_theme 或 apply_scaling 中
for btn in self.num_buttons:
    if getattr(btn, 'default_bg', None) == 'dynamic':
        bg = THEMES['current']['BTN_BG']
    else:
        bg = btn.default_bg
    btn.setStyleSheet(btn_style_template(bg, THEMES['current']['BTN_BORDER'], font_size_num, radius_num))
AnimatedLCD 呼吸闪烁
python 复制代码
class AnimatedLCD(QtWidgets.QLCDNumber):
    def __init__(self, digits=4, parent=None):
        super().__init__(digits, parent)
        self._font_px = 28
        self.opacity = 1.0
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.flicker)
        self.timer.start(2800)

    def _apply_theme(self):
        t = THEMES['current']
        style = f"""
            QLCDNumber {{
                background: {t['LCD_BG']};
                color: {t['ACCENT']};
                border: 2px solid {t['LCD_BORDER']};
                border-radius: 8px;
                padding: 6px;
                font: bold {self._font_px}px 'Consolas';
            }}
        """
        self.setStyleSheet(style)

    def flicker(self):
        self.opacity = 0.75 if self.opacity == 1.0 else 1.0
        self._apply_theme()
RealJoystick 核心回调
python 复制代码
class RealJoystick(QtWidgets.QWidget):
    pan_tilt_changed = QtCore.pyqtSignal(int, int)
    def mouseMoveEvent(self, e):
        if self.dragging:
            vec = e.pos() - self.center
            length = (vec.x() ** 2 + vec.y() ** 2) ** 0.5
            if length > self._max_radius and length != 0:
                scale = self._max_radius / length
                vec = QtCore.QPoint(int(vec.x() * scale), int(vec.y() * scale))
            self.pos = self.center + vec
            self.update()
            pan = int(vec.x() / self._max_radius * 127)
            tilt = int(-vec.y() / self._max_radius * 127)
            self.pan_tilt_changed.emit(pan, tilt)

三、运行环境与要求

最低配置:

  • 操作系统:Windows 7 SP1(32/64 位均可)
  • Python:3.7.9
  • 依赖库:
    • PyQt5==5.15.2
    • pyserial

安装命令:

bash 复制代码
pip install PyQt5==5.15.2 pyserial

运行方式:

bash 复制代码
python KBD300A_main.py

打包命令:

python 复制代码
pyinstaller --clean --noconfirm KBD300A_main.spec

打包版本文件:

txt 复制代码
# UTF-8
VSVersionInfo(
  ffi=FixedFileInfo(
    filevers=(1, 0, 0, 0),
    prodvers=(1, 0, 0, 0),
    mask=0x3f,
    flags=0x0,
    OS=0x40004,  # Windows NT 32-bit
    fileType=0x1,
    subtype=0x0,
    date=(0, 0)
  ),
  kids=[
    StringFileInfo([
      StringTable(
        '080404b0',  # 简体中文
        [
          StringStruct('CompanyName', '智码电子'),
          StringStruct('FileDescription', 'KBD300软键盘控制软件'),
          StringStruct('FileVersion', '1.0.0.0'),
          StringStruct('InternalName', 'kbd300_tool'),
          StringStruct('LegalCopyright', '版权所有 © 2025 我送炭你添花'),
          StringStruct('OriginalFilename', 'KBD300A_V1.0.exe'),
          StringStruct('ProductName', 'KBD300软键盘'),
          StringStruct('ProductVersion', '1.0.0.0')
        ]
      )
    ]),
    VarFileInfo([
      VarStruct('Translation', [0x0804, 1200])
    ])
  ]
)

双击运行,即刻出现一台 永不磨损、永不掉键 的 Pelco KBD300A!


四、运行界面

暗色主题:

浅色主题:

五、资源

源代码和打包后的exe文件,请点击(稍后上传)

六、下篇预告

下一篇(第 7 篇)将带来更强大的功能:

《内置完整宏脚本编辑器 + 实时解释器 + 无限长度 Pattern 录制与单步调试》

届时,这台"软件键盘"将拥有原装 KBD300A 永远不可能具备的 超级大脑

  • 支持 for/while 循环、条件判断、变量、延时、注释
  • 一键录制 → 自动生成可读脚本 → 无限次回放
  • 带语法高亮、单步调试、断点功能
    上一篇 目录 下一篇
相关推荐
山土成旧客6 小时前
【Python学习打卡-Day22】启航Kaggle:从路径管理到独立项目研究的全方位指南
开发语言·python·学习
我命由我123456 小时前
Python Flask 开发 - Flask 路径参数类型(string、int、float、path、uuid)
服务器·开发语言·后端·python·flask·学习方法·python3.11
大道随心7 小时前
【QT】自动化设备控制界面搭建
开发语言·qt·自动化
Chen--Xing7 小时前
LeetCode LCR 119.最长连续序列
c++·python·算法·leetcode·rust
BoBoZz197 小时前
ConnectivityFilter数据集中分离的区域或连通分量
python·vtk·图形渲染·图形处理
程序员杰哥7 小时前
如何使用Postman做接口自动化测试?
自动化测试·软件测试·python·测试工具·测试用例·接口测试·postman
最幸伏的人7 小时前
Pycharm2025.3版本使用UV搭建项目
python·pycharm·uv
天才测试猿7 小时前
Jmeter 命令行压测&生成HTML测试报告
自动化测试·软件测试·python·测试工具·jmeter·职场和发展·jenkins
道之极万物灭7 小时前
NiceGUI之Button操作(ElementPlus组件库)
python·elementui·web组件·nicegui