You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下PyQt6编写的Caps Lock检测程序返回值异常求助

解决Kali Linux下PyQt6 Caps Lock检测失效问题

问题描述

Kali系统无法运行自带键盘指示器,自行用PyQt6编写Caps Lock检测程序后出现异常:单独运行检测逻辑正常,但整合到PyQt6程序后,Windows平台运行正常,Linux平台反复按下Caps Lock时,程序始终返回相同的错误状态值。

问题根源

  1. 状态更新时机冲突:pynput的键盘监听器在Caps Lock按键按下的瞬间就触发回调,此时系统还未完成Caps Lock状态的切换,直接调用xset q读取到的是旧状态。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 20:05:15