专注于PyQt5 / Pyside2

Munshine

我正在创建AlbertAlfreduLauncher风格的启动器我的应用程序在后台运行,并在按下热键时显示。pynput过去常常听热键。我无法使用PyQt5热键的功能(不是吗?),因为我需要监听系统范围内的键盘事件,而不仅仅是应用程序范围。

按下快捷方式后,它将调用我的小部件的show()方法。唯一的问题是,我不能让我的窗口上,焦点回到尽管使用了raise_setFocusactivateWindow

我发现了一个(丑陋的)解决方法,其中包括打开QMessageBox(+调整其外观以使其不可见,但没有在示例代码中添加它)并在之后立即将其关闭。

当我在Linux上工作时,该解决方法正在完成任务,而我准备忘记它在完成任务时有多丑。但是我切换到Windows(我的应用程序也必须在其上运行),现在这个厚脸皮的把戏似乎导致应用程序冻结然后崩溃。业力?当然。

无论如何,如果我的应用程序不能引起关注,那它就毫无用处,所以我问了两个问题,我很高兴只解决了一个问题。:)

  • 您知道为什么显示QMessageBox会导致崩溃吗?
  • 您是否还有其他方法可以将注意力重新放在我的应用程序上?

这是一个示例代码。

非常感谢你 :)

编辑:我刚刚发现,即使停用QMessageBox解决方法,应用程序最终也会崩溃(在热键调用5、20、30之后)。因此,问题可能出在我将快捷方式绑定到GUI的方式上,我担心会出现线程问题,但这超出了我的了解:/

import sys
from PyQt5.QtWidgets import QLineEdit, QApplication, QMessageBox
from PyQt5.QtCore import QSize, Qt, QEvent
from pynput import keyboard


class Launcher(QLineEdit):
    def __init__(self):
        super().__init__()
        self.setFixedSize(QSize(600, 50))
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setPlaceholderText('Search...')

        self.installEventFilter(self)

        self.set_shortcut('<ctrl>+`')

    def set_shortcut(self, shortcut):
        def for_canonical(f):
            return lambda k: f(listener.canonical(k))

        hotkey = keyboard.HotKey(
            keyboard.HotKey.parse(shortcut),
            self.wake_up)

        listener = keyboard.Listener(
                on_press=for_canonical(hotkey.press),
                on_release=for_canonical(hotkey.release))

        listener.start()

    def wake_up(self):
        print('Waking up')
        self.show()
        self.cheeky_focus_stealer()

    def cheeky_focus_stealer(self):
        self.setFocus()
        self.raise_()
        self.activateWindow()

        # Working of linux, but causes freeze/crash on Windows 10
        message_box = QMessageBox(self)
        message_box.show()
        message_box.hide()

    def eventFilter(self, obj, event):
        if obj is self and event.type() == QEvent.KeyPress:
            if event.key() == Qt.Key_Escape:
                self.hide()
                return True

        return super().eventFilter(obj, event)


def main():
    app = QApplication(sys.argv)
    app.setQuitOnLastWindowClosed(False)

    window = Launcher()
    window.show()

    app.exec_()


if __name__ == "__main__":
    main()
Munshine

我发现了我的错误,所以我在这里发布了一段更新的代码,因为它可能对尝试将全局热键绑定到影响GUI的功能(也就是两个不同的线程通信)的人有所帮助。

我的错误确实是将热键触发的操作直接绑定到我的show()方法,这意味着pynput侦听器线程将尝试与进行通信QApplication

诀窍是使用pyqtSignal()和要求它触发show()方法。信号本身被热键触发。

在以一种干净的方式完成此操作之后,我cheeky_focus_stealer再次工作,因为它是从GUI线程运行的。

import sys
from PyQt5.QtWidgets import QLineEdit, QApplication, QMessageBox
from PyQt5.QtCore import QSize, Qt, QEvent, QObject, pyqtSignal
from pynput import keyboard


class Forwarder(QObject):
    signal = pyqtSignal()


class Launcher(QLineEdit):
    def __init__(self):
        super().__init__()
        self.setFixedSize(QSize(600, 50))
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setPlaceholderText('Search...')

        self.installEventFilter(self)

        self.set_shortcut('<ctrl>+`')

    def set_shortcut(self, shortcut):
        # The forwarder must be parented to the Launcher
        forwarder = Forwarder(parent=self)
        forwarder.signal.connect(self.wake_up)

        def for_canonical(f):
            return lambda k: f(listener.canonical(k))

        hotkey = keyboard.HotKey(
            keyboard.HotKey.parse(shortcut),
            forwarder.signal.emit)

        listener = keyboard.Listener(
                on_press=for_canonical(hotkey.press),
                on_release=for_canonical(hotkey.release))

        listener.start()

    def wake_up(self):
        print('Waking up')
        self.show()
        self.cheeky_focus_stealer()

    def cheeky_focus_stealer(self):
        self.setFocus()
        self.raise_()
        self.activateWindow()

        # Working of linux, but causes freeze/crash on Windows 10
        message_box = QMessageBox(self)
        message_box.show()
        message_box.hide()

    def eventFilter(self, obj, event):
        if obj is self and event.type() == QEvent.KeyPress:
            if event.key() == Qt.Key_Escape:
                self.hide()
                return True

        return super().eventFilter(obj, event)


def main():
    app = QApplication(sys.argv)
    app.setQuitOnLastWindowClosed(False)

    window = Launcher()
    window.show()

    app.exec_()


if __name__ == "__main__":
    main()

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

合并pyserial和pyside2 / pyqt5

来自分类Dev

从PyQt5迁移到Pyside2后,只要调用QFileDialog,QThread就会关闭

来自分类Dev

QGraphicsItem.setTransformations不能按预期工作(另:PySide2与PyQt5之间的差异)

来自分类Dev

其他进程在后台运行时如何显示PyQt5 / PySide2对话框

来自分类Dev

如何在Python / PyQt5 / PySide2 / Tkinter的任务栏中选择窗口工作区的特定部分显示在窗口缩略图中?

来自分类Dev

PyCharm无法调试Qt5(PySide2)代码-错误的'Shiboken.ObjectType'对象不可迭代

来自分类Dev

QOpenGLFunctions和PySide2

来自分类Dev

pyside2 QGraphicsPathItem WindingFill

来自分类Dev

PySide/PyQT5:如何从 QGraphicsItem 发出信号?

来自分类Dev

适用于Archlinux的Matplotlib的PyQt4,PyQt5或PySide

来自分类Dev

导入PySide2时ImportError

来自分类Dev

PySide2 findChild不返回

来自分类Dev

PySide2 - 更改表头背景颜色

来自分类Dev

如何在Windows for Python 2上安装PyQt5?

来自分类Dev

如何访问PySide2中选中的QCheckBox?

来自分类Dev

如何使用PySide2实现响应式画廊视图

来自分类Dev

QTextedit find()总是返回False(pyside2)

来自分类Dev

如何使用PySide2在qml中设置值?

来自分类Dev

使用Qt Designer时显示PySide2 QCharts

来自分类Dev

PySide2使用QProgressBar作为信号参数

来自分类Dev

在小部件Pyside2之间传递变量

来自分类Dev

PySide2 QOpenGLWidget按键事件不起作用

来自分类Dev

使用PySide2在Qt-Designer中嵌入PyQtGraph

来自分类Dev

如何使用PySide2使我的选择框正确移动?

来自分类Dev

具有指定参数的PySide2(5.14.2)信号

来自分类Dev

Pyside2 QGuiApplication,桂冻结按钮单击

来自分类Dev

在PySide2中协调绘制线和点

来自分类Dev

PySide2 / QLayout:无法向QHBoxLayout添加空布局

来自分类Dev

如何在QtCreator中配置PySide2 + QML?

Related 相关文章

  1. 1

    合并pyserial和pyside2 / pyqt5

  2. 2

    从PyQt5迁移到Pyside2后,只要调用QFileDialog,QThread就会关闭

  3. 3

    QGraphicsItem.setTransformations不能按预期工作(另:PySide2与PyQt5之间的差异)

  4. 4

    其他进程在后台运行时如何显示PyQt5 / PySide2对话框

  5. 5

    如何在Python / PyQt5 / PySide2 / Tkinter的任务栏中选择窗口工作区的特定部分显示在窗口缩略图中?

  6. 6

    PyCharm无法调试Qt5(PySide2)代码-错误的'Shiboken.ObjectType'对象不可迭代

  7. 7

    QOpenGLFunctions和PySide2

  8. 8

    pyside2 QGraphicsPathItem WindingFill

  9. 9

    PySide/PyQT5:如何从 QGraphicsItem 发出信号?

  10. 10

    适用于Archlinux的Matplotlib的PyQt4,PyQt5或PySide

  11. 11

    导入PySide2时ImportError

  12. 12

    PySide2 findChild不返回

  13. 13

    PySide2 - 更改表头背景颜色

  14. 14

    如何在Windows for Python 2上安装PyQt5?

  15. 15

    如何访问PySide2中选中的QCheckBox?

  16. 16

    如何使用PySide2实现响应式画廊视图

  17. 17

    QTextedit find()总是返回False(pyside2)

  18. 18

    如何使用PySide2在qml中设置值?

  19. 19

    使用Qt Designer时显示PySide2 QCharts

  20. 20

    PySide2使用QProgressBar作为信号参数

  21. 21

    在小部件Pyside2之间传递变量

  22. 22

    PySide2 QOpenGLWidget按键事件不起作用

  23. 23

    使用PySide2在Qt-Designer中嵌入PyQtGraph

  24. 24

    如何使用PySide2使我的选择框正确移动?

  25. 25

    具有指定参数的PySide2(5.14.2)信号

  26. 26

    Pyside2 QGuiApplication,桂冻结按钮单击

  27. 27

    在PySide2中协调绘制线和点

  28. 28

    PySide2 / QLayout:无法向QHBoxLayout添加空布局

  29. 29

    如何在QtCreator中配置PySide2 + QML?

热门标签

归档