pyqt6 subprocess.run 函数始终返回相同的值,即使大写锁定状态发生变化

问题描述 投票:0回答:1

由于键盘指示器小部件无法在我的kali系统上运行,因此我决定使用pyqt自己编写一个。我发现如果我把程序分离出来跑一下就正常了,但是用pyqt6就不行了。在Windows上运行正常,但是在Linux上却出现了一个很奇怪的问题。即使我反复按大写锁定,它仍然返回相同的错误值。

import subprocess
from time import sleep
while(True):
    print(subprocess.run("xset q | grep \"Caps Lock\" | awk -F': ' '{gsub(/[0-9]/,\"\",$3); print $3}'",
                                        stdout=subprocess.PIPE,
                                        shell=True,
                                        text=True).stdout.strip() == 'on')    
    sleep(0.3)
# pip install PyQt6 pynput
from platform import system
from sys import argv, exit

from PyQt6.QtCore import Qt
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:
            self.updateCapsLockStatus()

    def updateCapsLockStatus(self):
        new_status: bool = None
        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":
            import subprocess
            new_status = subprocess.run("xset q | grep \"Caps Lock\" | awk -F': ' '{gsub(/[0-9]/,\"\",$3); print $3}'",
                                        stdout=subprocess.PIPE,
                                        shell=True,
                                        text=True).stdout.strip() == 'on'
            
            print(new_status)
        self.show()
        self.status_label.setText("OFF" if not new_status else "ON")

    def mousePressEvent(self, event):
        self.hide()


if __name__ == '__main__':
    app = QApplication(argv)
    window = CapsLockDetector()
    window.show()
    exit(app.exec())

我希望我的程序返回正确的值

pyqt subprocess pyqt6 pynput capslock
1个回答
0
投票

在 Linux(使用 X11/Xorg)上,仅当按键释放时,大写锁定才会关闭。事实上,有一个相关报告也包含补丁,但不幸的是,即使在十年年后它也从未被合并!

因此,最安全的解决方案是仅依赖密钥释放:

    def setupKeyboardHook(self):
        listener = keyboard.Listener(on_release=self.on_key_release)
        listener.start()

    def on_key_release(self, key):
        if key == keyboard.Key.caps_lock:
            self.updateCapsLockStatus()

现在,由于这可能是针对长时间运行的程序,并且您可能仍然希望尽快看到更新的当前状态,因此您可以保留内部状态并仅在必要时更新它。另外,

class CapsLockDetector(QMainWindow):
    capsStatus = False

    def setupKeyboardHook(self):
        keyboard.Listener(
            on_press=self.on_key_press,
            on_release=self.on_key_release
        ).start()



    def on_key_release(self, key):
        if key == keyboard.Key.caps_lock:
            self.updateCapsLockStatus()
© www.soinside.com 2019 - 2024. All rights reserved.