【问题标题】:KeyPressEvent without FocusKeyPressEvent 没有焦点
【发布时间】:2021-12-03 03:29:06
【问题描述】:

我正在编写一个简单的 GUI,它将在特定点打开一个 opencv 窗口。这个窗口有一些非常基本的 keyEvents 来控制它。我想通过一些功能来推进这一点。由于我的 QtGui 是我的控制器,我认为使用 KeyPressedEvent 是一个好方法。我的问题是,如果我在 opencv 窗口上处于活动状态,我无法触发 KeyEvent。

如果我的 Gui 失焦,我该如何触发 KeyEvent?

我真的需要使用 GrabKeyboard 吗?

以下代码重现了我的问题:

import sys
from PyQt5.QtWidgets import (QApplication, QWidget)
from PyQt5.Qt import Qt
import cv2


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.first = True

    def openselect(self):
        im = cv2.imread(str('.\\images\\Steine\\0a5c8e512e.jpg'))
        self.r = cv2.selectROI("Image", im)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Space and self.first:
            self.openselect()
            self.first = False
        print('Key Pressed!')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = MainWindow()

    win.show()
    sys.exit(app.exec_())

【问题讨论】:

  • 这是我的最低要求:如果我失去对 MainWindow 的关注,则不会触发 keyPressEvent。如果我的窗口处于活动状态并且我按下任何按钮,控制台就会打印。如果不是什么都不会发生。
  • 不要专注于最小值,因为它是最简单最琐碎的,因为它只是擦除代码,你必须专注于再现性。我指出这一点是因为在您的帖子中您谈到了 opencv,但在您的代码中我没有看到任何内容。
  • 你可以用这个简单的代码重现我的问题。我只提到了 opencv,因为它打开了第二个窗口,我必须与之交互。问题与opencv无关。所以我没有标记opencv。
  • 我已经测试了你的代码,我得到“Key Pressed!”这不是你所说的。

标签: python pyqt5 keypress


【解决方案1】:

keyPressEvent 方法仅在小部件具有焦点时才被调用,因此如果焦点有另一个应用程序,则不会通知它,因此如果要检测键盘事件,则必须处理 OS 库,但在 python 中它们已经存在将这些更改报告为pyinput(python -m pip install pyinput) 的库:

import sys

from PyQt5 import QtCore, QtWidgets

from pynput.keyboard import Key, Listener, KeyCode


class KeyMonitor(QtCore.QObject):
    keyPressed = QtCore.pyqtSignal(KeyCode)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.listener = Listener(on_release=self.on_release)

    def on_release(self, key):
        self.keyPressed.emit(key)

    def stop_monitoring(self):
        self.listener.stop()

    def start_monitoring(self):
        self.listener.start()


class MainWindow(QtWidgets.QWidget):
    pass


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    monitor = KeyMonitor()
    monitor.keyPressed.connect(print)
    monitor.start_monitoring()

    window = MainWindow()
    window.show()

    sys.exit(app.exec_())

【讨论】:

  • 嘿,这按预期工作,到目前为止谢谢。我对如何在其他方面使用键输入感到困惑,然后只是打印。在我的示例中,我想在 QMainwindow 中切换复选框的状态。
  • 好吧自己想通了。我在我的主窗口中加载了监视器并将自己设置为父级。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-22
  • 1970-01-01
  • 1970-01-01
  • 2021-08-30
  • 2021-08-15
  • 2020-11-07
相关资源
最近更新 更多