【问题标题】:Splashsceen of PyInstaller: main window not showing on topPyInstaller 的 Splashsceen:主窗口未显示在顶部
【发布时间】:2023-01-26 08:52:26
【问题描述】:

我正在使用 pyinstaller 将我的应用程序捆绑到 Windows(OS) 上,并添加了启动画面选项。加载主窗口并关闭启动画面后,该窗口将停留在背景上(如果您打开了其他窗口,则在其他窗口后面)。 我试过 .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')

【问题讨论】:

  • 感谢您的输入,已经有了,它加载速度更快,因此飞溅的时间少了很多,但它仍然没有弹出

标签: python-3.x pyinstaller splash-screen


【解决方案1】:

这是我所做的,但请注意,我设置了初始屏幕,因此它并不总是在最上面。在那种情况下我没有测试过,这种方法在那种情况下可能不起作用,但它可能会帮助你弄清楚一些事情。

此示例的另一个注意事项是,我通过枚举 Windows 并按名称“tk”查找启动画面窗口。这是非常通用的,如果打开了其他 tk 窗口,则可能会失败。可能值得考虑使用更独特的字符串创建自定义的 pyinstaller 引导加载程序。

此代码的行为是:

  • 运行该应用程序,初始屏幕不是最上面的,因此您可以轻松切换到其他应用程序。
  • 当应用程序运行时,它会将自己的窗口移动到启动画面前面并关闭启动画面,并保持在 Z 顺序中的那个位置。
  • 如果初始屏幕是活动窗口,则应用程序窗口变为活动窗口。
  • 如果初始屏幕未激活(例如,您在加载此应用程序时切换到另一个应用程序),则应用程序任务栏条目将闪烁。

Python 主要代码(它是从我的实际应用程序中复制和粘贴的,我现在不能轻易提取最小代码):

import sys
from PySide6 import QtCore
from PySide6.QtWidgets import QApplication, QMainWindow
import win32gui
import platform
import importlib
from ui_MainWindow import Ui_MainWindow

pyi_splash_spec = importlib.util.find_spec("pyi_splash")
if pyi_splash_spec is not None:
    import pyi_splash


#
class MyMainWindow(QMainWindow):
    #
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

def winEnumHandler(hwnd, ctx):
    if win32gui.IsWindowVisible(hwnd):
        n = win32gui.GetWindowText(hwnd)
        if n == 'tk':
            ctx.append(hwnd)


def MoveAboveSplash(hwnd):
    splashHWnd = []
    win32gui.EnumWindows(winEnumHandler, splashHWnd)
    if len(splashHWnd) > 0:
        if win32gui.GetForegroundWindow() == splashHWnd[0]:
            flags = 0x03 # SWP_NOMOVE | SWP_NOSIZE
        else:
            flags = 0x13 # SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE

        # Move our window so it is immediately after the splash window.
        # Activate if splash was foreground, otherwise not.
        win32gui.SetWindowPos(hwnd, splashHWnd[0], 0, 0, 0, 0, flags)

        # Now move the splash window so that it is behind the main window.
        # Always "no activate"
        win32gui.SetWindowPos(splashHWnd[0], hwnd, 0, 0, 0, 0, 0x13)

        # Make ourselves the foreground window.
        try:
            win32gui.SetForegroundWindow(hwnd)
        except:
            pass

#
def main():
    QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
    QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps)

    app = QApplication(sys.argv)
    #app.setStyle('WindowsVista')

    mainWindow = MyMainWindow()
    mainWindow.show()

    if pyi_splash_spec is not None and pyi_splash.is_alive():
        if platform.system() == 'Windows':
            MoveAboveSplash(mainWindow.winId())

        pyi_splash.close()

    app.exec()

#
if (__name__ == '__main__'):
    main()

pyinstaller 的规范文件:

# -*- mode: python ; coding: utf-8 -*-


block_cipher = None


a = Analysis(
    ['MyApp/minimal.py'],
    pathex=['MyApp'],
    binaries=[],
    datas=[],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=['sqlite', 'tbb'],
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=block_cipher,
    noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
splash = Splash(
    'splash.png',
    binaries=a.binaries,
    datas=a.datas,
    text_pos=None,
    text_size=12,
    minify_script=True,
    always_on_top=False,
)

exe = EXE(
    pyz,
    a.scripts,
    splash,
    [],
    exclude_binaries=True,
    name='MyApp',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=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='MyApp',
)

【讨论】:

    猜你喜欢
    • 2015-11-20
    • 1970-01-01
    • 2019-12-05
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多