0

我想以是否按下修饰键 (Ctrl) 为条件进行操作。我发现的一种解决方法是安装一个事件过滤器并用于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_()

但是,我担心这是对.queryKeyboardModifiers()and.keyboardModifiers()函数的意外使用,因此以后可能会导致更多麻烦。是否有适当的方法来检测何时单独按下/释放修改键(即没有按下任何其他键)?

虽然我使用的是 PySide6,但如果它们有帮助,我会接受 C++ 或 PyQt 中的答案。

4

1 回答 1

3

您当前正在做的是检查 Ctrl 每次事件发生时是否按下了键(例如单击、移动、调整大小等),这似乎不是您的目标,而只是检测何时发生更改,因此您必须改进Qt.KeyPress 或 Qt.KeyRelease 事件的过滤器。另一方面,如果您想检测另一个子窗口小部件何时使用事件,则您的方法将不起作用,因为它不会传播到父窗口,而是最好将过滤器应用于 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_()
于 2021-04-28T20:29:37.463 回答