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
相关产品推荐
相关产品推荐

