首页 > 解决方案 > 激活窗口停止主循环

问题描述

我有一个简单的 GUI 应用程序,我想Alt+M在窗口最小化时连接以恢复窗口。相关代码是这样的:

from pynput import keyboard
import sys, os, _thread
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        _thread.start_new_thread(self.hotkeyLoop, (self,))

        self.setWindowFlags(self.windowFlags() | QtCore.Qt.CustomizeWindowHint)
        self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowCloseButtonHint)

        self.show()

    def hotkeyLoop(self, window):
        COMBINATIONS = [
            {keyboard.Key.alt_l, keyboard.KeyCode(char='m')},
            {keyboard.Key.alt_l, keyboard.KeyCode(char='M')}
        ]

        # The currently active modifiers
        current = set()

        def execute():
            print('alt+m')
            self.setWindowState(QtCore.Qt.WindowActive)

        def on_press(key):
            if any([key in COMBO for COMBO in COMBINATIONS]):
                current.add(key)
                if any(all(k in current for k in COMBO) for COMBO in COMBINATIONS):
                    execute()

        def on_release(key):
            if any([key in COMBO for COMBO in COMBINATIONS]):
                current.remove(key)

        with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
            listener.join()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWindow = MainWindow()
    sys.exit(app.exec_())

中的代码hotkeyLoop实际上是我用来捕捉热键的复制粘贴代码。我知道这段代码确实有效,因为我window.show()在窗口关闭时在同一个应用程序中使用了它。这很完美。但我决定让窗口无法关闭,并在它最小化时使用热键显示它。但是每当我按下热键组合时,窗口就会出现,但它完全是白色的并且停止响应。那么我别无选择,只能终止它。

像这样:

为什么会发生这种情况,我该如何解决?

标签: pythonpyqt5

解决方案


一般来说,如果你的代码有一个除了 GUI 的主循环之外的无限循环,你的 GUI 将停止响应。keyboard.Listener.join()实际上是一个无限循环——只要听者还活着,它就会无限期地阻塞。

您可以不调用 join,在这种情况下,主线程将根据需要继续执行 GUI 主循环。只要确保保持对侦听器线程的永久引用,这样它就不会过早地收集垃圾。

改变:

with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
    listener.join()

至:

self.listener = keyboard.Listener(on_press=on_press, on_release=on_release)

推荐阅读