PyInstaller启动画面关闭后Windows平台主窗口无法前置求助
问题:PyInstaller带启动画面后主窗口被遮挡在后台(Windows)
在Windows系统中使用PyInstaller打包PyQt5应用,添加启动画面(splash screen)后,关闭启动画面加载主窗口时,主窗口会停留在后台(被其他打开的窗口遮挡)。尝试过调用.raise_()、.ActivateWindow()、.setVisible(True)方法均无效,禁用启动画面后功能正常,但因应用加载耗时必须保留启动画面,寻求解决方案。
最小复现代码
''' Created on Oct 17, 2022 @author: mdelu ''' import sys from PyQt5 import QtWidgets try: import pyi_splash except: pass # print('Ejecucion en eclipse sin splash') if __name__ == '__main__': try: if (pyi_splash.is_alive()): pyi_splash.close() except: pass app = QtWidgets.QApplication(sys.argv) main_window = QtWidgets.QMainWindow() ui = QtWidgets.QWidget(main_window) main_window.resize(800, 600) main_window.show() sys.exit(app.exec_())
对应的.spec文件
a = Analysis(['main.py'], binaries=[], hiddenimports=[], hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, noarchive=False, ) splash_image = 'path' splash = Splash(splash_image, binaries=a.binaries, datas=a.datas, minify_script=False) pyz = PYZ(a.pure, a.zipped_data) exe = EXE(pyz, splash, a.scripts, [], exclude_binaries=True, name='main', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, console=False, disable_windowed_traceback=False, target_arch=None, codesign_identity=None, entitlements_file=None) coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, splash.binaries, strip=False, upx=True, upx_exclude=[], name='exe')
解决方案
方法1:调整启动画面关闭时机+Windows原生API强制激活
核心思路是先显示主窗口,再关闭启动画面,同时调用Windows系统API强制将主窗口设为前台窗口(PyQt的激活方法可能因系统焦点机制限制失效)。
修改后的代码:
''' Created on Oct 17, 2022 @author: mdelu ''' import sys from PyQt5 import QtWidgets, QtCore try: import pyi_splash except: pass # print('Ejecucion en eclipse sin splash') if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) main_window = QtWidgets.QMainWindow() ui = QtWidgets.QWidget(main_window) main_window.resize(800, 600) # 先显示主窗口 main_window.show() # 再关闭启动画面 try: if pyi_splash.is_alive(): pyi_splash.close() except: pass # Windows下调用原生API强制激活窗口 if sys.platform == 'win32': import ctypes hwnd = int(main_window.winId()) # 强制设置为前台窗口 ctypes.windll.user32.SetForegroundWindow(hwnd) # 配合PyQt的方法巩固效果 main_window.raise_() main_window.activateWindow() sys.exit(app.exec_())
方法2:延迟关闭启动画面
如果方法1仍有问题,可以给启动画面的关闭操作加短暂延迟,让主窗口有足够时间完成焦点获取:
# 替换原有的启动画面关闭代码 try: if pyi_splash.is_alive(): # 延迟100毫秒关闭启动画面 QtCore.QTimer.singleShot(100, pyi_splash.close) except: pass
问题原因
Windows系统中,PyInstaller的启动画面是独立的顶层窗口,关闭时会抢占焦点并带走系统的前台窗口权限,导致后续创建的PyQt主窗口无法自动获取前台焦点。PyQt自带的窗口激活方法受系统焦点规则限制,无法强制突破,而调用Windows原生的SetForegroundWindowAPI可以绕过这一限制,确保主窗口显示在最前端。
内容的提问来源于stack exchange,提问作者tinchodeluca
相关产品推荐
相关产品推荐

