You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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_())

代码说明

  1. PopupWindow类中,Qt.Tool标志让弹窗成为工具窗口,不会抢占主窗口焦点;Qt.NonModal确保主窗口可正常操作
  2. 打开弹窗用show()方法,而不是模态窗口常用的exec_(),后者会阻塞主窗口
  3. 弹窗设置了父窗口为MainWindow,这样弹窗会和主窗口关联,主窗口关闭时弹窗也会跟着关闭

这样你点击按钮打开弹窗后,就能同时操作主窗口的QDoubleSpinBox啦,完全不用碰QHoverEvent~

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

火山引擎 最新活动