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

MacOS下PyQt5应用如何实现不获取焦点但仍可交互?

解决PyQt5窗口不抢夺EOS软件焦点的方案

关键调整点

  • 子控件(QDial)不能设置窗口标志,改用setFocusPolicy(Qt.NoFocus)禁用焦点获取
  • 主窗口补充鼠标事件处理,确保交互时不激活当前窗口
  • 核心是窗口和控件的焦点属性配置,无需全局应用额外设置

修改后的完整代码

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys

class Dial(QDial):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setNotchesVisible(False)
        self.setWrapping(True)
        self.setRange(0, 25)
        self.valueChanged.connect(self.emitValueChanged)
        # 子控件禁用焦点获取,替换原错误的窗口标志设置
        self.setFocusPolicy(Qt.NoFocus)
    
    @property
    def dialVal(self):
        return self.value()

    def emitValueChanged(self, dialVal):
        print(self.value())

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # 组合窗口标志:无边框、不接收焦点、置顶、不激活显示
        self.setWindowFlags(
            Qt.Window 
            | Qt.FramelessWindowHint 
            | Qt.WindowDoesNotAcceptFocus 
            | Qt.WindowStaysOnTopHint
        )
        self.setAttribute(Qt.WA_ShowWithoutActivating)
        self.setFocusPolicy(Qt.NoFocus)
        
        self.dial = Dial()
        layout = QVBoxLayout()
        layout.addWidget(self.dial)
        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

    # 重写鼠标事件,阻止窗口获取焦点
    def mousePressEvent(self, event):
        event.ignore()
        super().mousePressEvent(event)
    
    def mouseReleaseEvent(self, event):
        event.ignore()
        super().mouseReleaseEvent(event)
    
    def mouseMoveEvent(self, event):
        event.ignore()
        super().mouseMoveEvent(event)

app = QApplication(sys.argv)
# 可选:设置应用级别的焦点策略(部分平台生效)
app.setFocusPolicy(Qt.NoFocus)
screen = MainWindow()
screen.show()
sys.exit(app.exec_())

极端情况处理

如果上述配置后仍存在焦点抢夺,可通过系统API强制将焦点切回EOS:

  • Windows:使用pywin32模块调用系统接口
import win32gui
# 替换为EOS软件的实际窗口标题
eos_window_title = "ETC EOS"
eos_handle = win32gui.FindWindow(None, eos_window_title)
if eos_handle:
    win32gui.SetForegroundWindow(eos_handle)
  • Linux:通过subprocess调用xdotool工具
import subprocess
# 替换为EOS窗口的类名或标题
subprocess.run(["xdotool", "windowactivate", "--sync", "$(xdotool search --name 'ETC EOS')"])
  • macOS:使用pyobjc操作AppKit框架
from AppKit import NSWorkspace
workspace = NSWorkspace.sharedWorkspace()
for app in workspace.runningApplications():
    if app.localizedName() == "EOS":
        app.activateWithOptions_(0)
        break

无需更换Python框架,PyQt5完全可以满足需求,核心是正确配置焦点属性和事件拦截。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:06:20