简体   繁体   English

检测何时按下 Ctrl(或其他修饰键)的正确方法

[英]Proper way to detect when Ctrl (or other modifier key) is pressed

I want to condition an action on whether or not a modifier key (Ctrl) is pressed.我想以是否按下修饰键 (Ctrl) 为条件进行操作。 One workaround I have found is to install an event filter and use QApplication.queryKeyboardModifiers() to detect when Ctrl is pressed, and QApplication.keyboardModifiers() to detect when Ctrl is released:我发现的一种解决方法是安装一个事件过滤器并使用QApplication.queryKeyboardModifiers()来检测何时Ctrl ,并使用QApplication.keyboardModifiers()来检测何时释放Ctrl

from PySide6.QtCore import Qt, Signal
from PySide6.QtWidgets import QApplication, QMainWindow

class MainWindow(QMainWindow):

    ctrl_signal = Signal(bool)

    def __init__(self):
        QMainWindow.__init__(self)
        self.installEventFilter(self)
        self.ctrl_signal.connect(self.ctrl_slot)

    def eventFilter(self, _object, e):
        if QApplication.queryKeyboardModifiers() == Qt.CTRL: # This runs twice, and only on key press (not release)
            print("Ctrl pressed")
            self.ctrl_signal.emit(True)
        elif QApplication.keyboardModifiers() == Qt.CTRL: # This runs once, but only on release
            print("Ctrl released")
            self.ctrl_signal.emit(False)
        return False

    def ctrl_slot(self, e):
        print("e: ", e)  # Do something

app = QApplication([])
window = MainWindow()
window.show()
app.exec_()

However, I am concerned that this is an unintended use of the .queryKeyboardModifiers() and .keyboardModifiers() functions, and therefore will likely lead to more trouble later on.但是,我担心这是对.queryKeyboardModifiers().keyboardModifiers()函数的意外使用,因此以后可能会导致更多麻烦。 Is there a proper way to detect when a modifier key is pressed/released in isolation (ie without any other keys being pressed)?是否有适当的方法来检测何时单独按下/释放修改键(即没有按下任何其他键)?

Though I am using PySide6, I'll accept answers in C++ or PyQt if they're helpful.虽然我使用的是 PySide6,但如果有帮助,我会接受 C++ 或 PyQt 中的答案。

What you are currently doing is to check if the Ctrl key was pressed every time an event happens (for example click, move, resize, etc) and it seems that that is not your goal but only to detect when is the change so you must improve your filter for the Qt.KeyPress or Qt.KeyRelease event.您当前正在做的是检查每次事件发生时是否按下了Ctrl键(例如单击、移动、调整大小等),这似乎不是您的目标,而只是检测何时发生更改,所以您必须针对 Qt.KeyPress 或 Qt.KeyRelease 事件改进您的过滤器。 On the other hand, your method will not work if you want to detect when another child widget consumes an event since it will not be propagated to the parent, instead it is better to apply the filter to the QWindow since the keyboard events arrive when it has the focus and does not depend on the logic of the children.另一方面,如果您想检测另一个子小部件何时使用事件,则您的方法将不起作用,因为它不会传播到父小部件,而是最好将过滤器应用于 QWindow,因为键盘事件在它到达时到达有重点,不依赖孩子的逻辑。

from PySide6.QtCore import Qt, Signal, QObject, QEvent
from PySide6.QtWidgets import QApplication, QMainWindow


class ControlHelper(QObject):
    ctrl_signal = Signal(bool)

    def __init__(self, window):
        super().__init__(window)
        self._window = window

        self.window.installEventFilter(self)

    @property
    def window(self):
        return self._window

    def eventFilter(self, obj, event):
        if obj is self.window:
            if event.type() == QEvent.KeyPress:
                if event.key() == Qt.Key_Control:
                    self.ctrl_signal.emit(True)
            if event.type() == QEvent.KeyRelease:
                if event.key() == Qt.Key_Control:
                    self.ctrl_signal.emit(False)
        return super().eventFilter(obj, event)


class MainWindow(QMainWindow):
    ctrl_signal = Signal(bool)

    def ctrl_slot(self, e):
        print("e: ", e)


app = QApplication([])
window = MainWindow()
window.show()

helper = ControlHelper(window.windowHandle())
helper.ctrl_signal.connect(window.ctrl_slot)

app.exec_()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM