Qt窗口焦点传递:弹出窗口打开时如何仍可操作主窗口
解决PyQt5弹出窗口不抢占焦点、主窗口可交互的问题
嗨,其实你完全不用折腾QHoverEvent啦,这个需求用Qt自带的窗口属性就能轻松搞定!核心是把弹出窗口设置为非模态的工具窗口,这样它就不会抢走主窗口的焦点,你照样能操作主窗口的QDoubleSpinBox或者其他控件。
关键设置要点
- 给弹出窗口设置
Qt.Tool窗口标志:工具窗口默认不会获取焦点,也不会在任务栏单独显示,适合做辅助弹窗 - 明确设置窗口模态为
Qt.NonModal:确保主窗口不受弹窗阻塞,能正常交互 - 可选添加
Qt.WindowStaysOnTopHint:让弹窗始终保持在主窗口上方,避免被遮挡(根据你的需求选择)
完整代码示例
import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( QApplication, QMainWindow, QWidget, QPushButton, QDoubleSpinBox, QVBoxLayout, QLabel ) class PopupWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) # 设置窗口属性,核心就在这两行 self.setWindowFlags(Qt.Tool | Qt.WindowStaysOnTopHint) self.setWindowModality(Qt.NonModal) # 弹窗的UI内容 layout = QVBoxLayout() layout.addWidget(QLabel("我是不会抢焦点的弹窗!")) self.setLayout(layout) self.resize(200, 100) class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("主窗口") self.resize(400, 200) # 主窗口UI central_widget = QWidget() layout = QVBoxLayout(central_widget) # 按钮用于打开弹窗 self.open_btn = QPushButton("打开弹窗") self.open_btn.clicked.connect(self.open_popup) layout.addWidget(self.open_btn) # 可交互的QDoubleSpinBox self.spin_box = QDoubleSpinBox() self.spin_box.setRange(0.0, 100.0) layout.addWidget(self.spin_box) self.setCentralWidget(central_widget) # 弹窗实例 self.popup = None def open_popup(self): if not self.popup or not self.popup.isVisible(): self.popup = PopupWindow(self) self.popup.show() # 用show()而不是exec_(),exec_()是模态的 if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
代码说明
PopupWindow类中,Qt.Tool标志让弹窗成为工具窗口,不会抢占主窗口焦点;Qt.NonModal确保主窗口可正常操作- 打开弹窗用
show()方法,而不是模态窗口常用的exec_(),后者会阻塞主窗口 - 弹窗设置了父窗口为
MainWindow,这样弹窗会和主窗口关联,主窗口关闭时弹窗也会跟着关闭
这样你点击按钮打开弹窗后,就能同时操作主窗口的QDoubleSpinBox啦,完全不用碰QHoverEvent~
内容的提问来源于stack exchange,提问作者218




