You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySide6中QMessageBox在循环中引发界面假死问题求助

问题分析

你的程序出现假死的核心原因有两个:

  • hotkey方法中的while True死循环完全阻塞了Qt的事件循环,导致界面无法处理任何用户交互(包括QMessageBox的显示和响应)。
  • 使用第三方keyboard库的轮询方式(keyboard.is_pressed)与Qt的事件驱动模型冲突,进一步加剧了界面阻塞。

另外代码里还有两处小bug:

  • self.Hotkey == True是比较操作而非赋值,应改为self.Hotkey = True
  • position_list和Hotkey是类属性,会被所有实例共享,应改为实例属性
修复后的代码
from PySide6.QtWidgets import *
from PySide6.QtGui import *
from PySide6.QtCore import *
import pyautogui
import sys

class Window_controller(QWidget):
    def __init__(self):
        super().__init__()
        self.Hotkey = False  # 改为实例属性
        self.position_list = []  # 改为实例属性
        
        self.layout = QVBoxLayout(self)
        self.label = QLabel("123")
        self.label.setFont(QFont("", 20))
        self.layout.addWidget(self.label)
        
        # 注册Qt原生快捷键,替代第三方keyboard库
        self.register_shortcuts()

    def register_shortcuts(self):
        # F11 切换热键激活状态
        QShortcut(QKeySequence(Qt.Key_F11), self, self.toggle_hotkey_mode)
        # 注册F1-F4快捷键,默认禁用
        self.f1_shortcut = QShortcut(QKeySequence(Qt.Key_F1), self, self.F1)
        self.f2_shortcut = QShortcut(QKeySequence(Qt.Key_F2), self, self.F2)
        self.f3_shortcut = QShortcut(QKeySequence(Qt.Key_F3), self, self.F3)
        self.f4_shortcut = QShortcut(QKeySequence(Qt.Key_F4), self, self.F4)
        self.toggle_hotkey_shortcuts(False)

    def toggle_hotkey_mode(self):
        self.Hotkey = not self.Hotkey
        if self.Hotkey:
            self.label.setText("Activated")
            self.toggle_hotkey_shortcuts(True)
        else:
            self.label.setText("")
            self.toggle_hotkey_shortcuts(False)

    def toggle_hotkey_shortcuts(self, enabled):
        self.f1_shortcut.setEnabled(enabled)
        self.f2_shortcut.setEnabled(enabled)
        self.f3_shortcut.setEnabled(enabled)
        self.f4_shortcut.setEnabled(enabled)

    def F1(self):
        if len(self.position_list) >= 2:
            pyautogui.moveTo(x=self.position_list[0], y=self.position_list[1])
        else:
            self.set_position()

    def F2(self):
        if len(self.position_list) >= 4:
            pyautogui.moveTo(x=self.position_list[2], y=self.position_list[3])
        else:
            self.set_position()

    def F3(self):
        if len(self.position_list) >= 6:
            pyautogui.moveTo(x=self.position_list[4], y=self.position_list[5])
        else:
            self.set_position()

    def F4(self):
        if len(self.position_list) >= 8:
            pyautogui.moveTo(x=self.position_list[6], y=self.position_list[7])
        else:
            self.set_position()

    def set_position(self):
        self.position_list.clear()
        for key in ["F1", "F2", "F3", "F4"]:
            # 模态对话框由Qt事件循环管理,不会阻塞界面
            QMessageBox.information(
                self, 
                f"设置{key}位置", 
                "请将鼠标移动到目标位置,然后点击确定"
            )
            pos = pyautogui.position()
            self.position_list.append(pos.x)
            self.position_list.append(pos.y)
        print("已保存位置:", self.position_list)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = Window_controller()
    win.show()
    sys.exit(app.exec())
关键修复点
  • 移除死循环与第三方库依赖:改用Qt原生QShortcut处理热键,完全适配Qt事件驱动模型,彻底解决界面阻塞问题。
  • 分离热键激活状态:通过toggle_hotkey_mode方法切换热键的启用/禁用状态,无需轮询检测。
  • 修正属性作用域:将Hotkey和position_list改为实例属性,避免多实例共享数据的问题。
  • 优化位置设置逻辑:清空旧位置后重新设置,确保列表长度准确;模态对话框由Qt自动管理事件循环,不会导致假死。

内容的提问来源于stack exchange,提问作者Dylan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 22:45:44