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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 07:40:20