Linux下PyQt6编写的Caps Lock检测程序返回值异常求助
解决Kali Linux下PyQt6 Caps Lock检测失效问题
问题描述
Kali系统无法运行自带键盘指示器,自行用PyQt6编写Caps Lock检测程序后出现异常:单独运行检测逻辑正常,但整合到PyQt6程序后,Windows平台运行正常,Linux平台反复按下Caps Lock时,程序始终返回相同的错误状态值。
问题根源
- 状态更新时机冲突:pynput的键盘监听器在Caps Lock按键按下的瞬间就触发回调,此时系统还未完成Caps Lock状态的切换,直接调用
xset q读取到的是旧状态。 xset输出解析不稳定:xset q的输出格式可能因系统配置变化,导致awk解析逻辑出错,返回错误的状态值。
修复方案
1. 延迟读取状态
通过Qt的定时器延迟100ms再读取状态,确保系统完成Caps Lock的状态切换。
2. 使用更可靠的状态查询工具
替换xset q为xkbcli state,该工具输出格式更固定,避免解析错误(Kali Linux默认预装xkbcli)。
3. 优化代码结构
将依赖库的导入移至顶部,避免重复导入影响性能。
修改后的完整代码
# pip install PyQt6 pynput from platform import system from sys import argv, exit import subprocess from PyQt6.QtCore import Qt, QTimer from PyQt6.QtGui import QPalette, QColor, QFont from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel from pynput import keyboard class CapsLockDetector(QMainWindow): def __init__(self): super().__init__() self.status_label = None self.initUI() self.setupKeyboardHook() def initUI(self): self.setWindowTitle('Caps Lock Detector') self.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint | Qt.WindowType.FramelessWindowHint) self.setGeometry(0, 0, 400, 120) palette = self.palette() palette.setColor(QPalette.ColorRole.Window, QColor(10, 10, 10)) self.setPalette(palette) screen_geometry = QApplication.primaryScreen().geometry() self.move(screen_geometry.x(), screen_geometry.y()) self.status_label = QLabel(self) self.status_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.setCentralWidget(self.status_label) self.status_label.setStyleSheet("color: white;") font = QFont("Consolas", 40) self.status_label.setFont(font) self.updateCapsLockStatus() def setupKeyboardHook(self): listener = keyboard.Listener(on_press=self.on_key_press) listener.start() def on_key_press(self, key): if key == keyboard.Key.caps_lock: # 延迟100ms确保系统完成Caps Lock状态切换 QTimer.singleShot(100, self.updateCapsLockStatus) def updateCapsLockStatus(self): new_status: bool = False if system() == "Windows": import ctypes hllDll = ctypes.WinDLL("User32.dll") VK_CAPITAL = 0x14 new_status = hllDll.GetKeyState(VK_CAPITAL) not in [0, 65408] elif system() == "Linux": # 使用xkbcli获取更稳定的Caps Lock状态 result = subprocess.run( "xkbcli state | grep \"Caps Lock\" | awk '{print $4}'", stdout=subprocess.PIPE, shell=True, text=True ).stdout.strip() new_status = result == 'on' print(new_status) self.status_label.setText("OFF" if not new_status else "ON") self.show() def mousePressEvent(self, event): self.hide() if __name__ == '__main__': app = QApplication(argv) window = CapsLockDetector() window.show() exit(app.exec())
额外说明
- 如果系统未预装
xkbcli,可通过sudo apt install xkbcommon-tools安装。 - 延迟时间可根据实际情况调整(50-200ms均可),确保状态更新完成即可。
内容的提问来源于stack exchange,提问作者Sepu Ling
相关产品推荐
相关产品推荐

