使用PyInstaller丢失按钮图标

问题描述

当我尝试使用pyinstaller创建onefile可执行文件时,所有按钮图标均被删除。 我想使用相对路径,以便.exe也可以在其他计算机上运行。 我发现了一些旧的帖子,但没有使它们起作用。

Python代码

import sys
from PyQt5 import QtCore,QtGui,QtWidgets


class Ui_MainWindow(QtWidgets.QMainWindow):

    def __init__(self,debugging=False):
        super().__init__()
        self.__setupUi()
        self.__retranslateUi()
        QtCore.QMetaObject.connectSlotsByName(self)
        self.show()

    def __setupUi(self):        
        self.setobjectName('MainWindow')
        self.resize(400,100)
        
        self.centralwidget=QtWidgets.QWidget(self)
        self.centralwidget.setobjectName('centralwidget')
        self.verticalLayout=QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setobjectName('verticalLayout')
        self.pushButton=QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setText('')
        icon=QtGui.QIcon()
        icon.addpixmap(QtGui.Qpixmap('Icons/test.png'),QtGui.QIcon.normal,QtGui.QIcon.Off)
        self.pushButton.setIcon(icon)
        self.pushButton.setIconSize(QtCore.QSize(32,32))
        self.pushButton.setobjectName('pushButton')
        self.verticalLayout.addWidget(self.pushButton)
        self.setCentralWidget(self.centralwidget)

    def __retranslateUi(self):
        _translate=QtCore.QCoreApplication.translate
        self.setwindowTitle(_translate('MainWindow','MainWindow'))


if __name__=='__main__':
    app=QtWidgets.QApplication(sys.argv)
    uiObj=Ui_MainWindow()
    sys.exit(app.exec())

PyInstaller命令:

python -m PyInstaller --onefile --windowed --add-data Icons/*.png;Icons test.py

.spec内容

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

block_cipher = None


a = Analysis(['test.py'],pathex=['C:\\Users\\User\\Desktop\\Neuer Ordner'],binaries=[],datas=[('Icons/*.png','Icons')],hiddenimports=[],hookspath=[],runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)
pyz = PYZ(a.pure,a.zipped_data,cipher=block_cipher)
exe = EXE(pyz,a.scripts,a.binaries,a.zipfiles,a.datas,[],name='test',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,upx_exclude=[],runtime_tmpdir=None,console=False )

那该如何解决呢? 谢谢。

解决方法

所以今天我找到了解决方案。这篇旧文章(link)确实很有帮助。 我的文件夹结构例如:

Folder
    - test.py
    - absolutePath.py
    - Icons

需要脚本absolutePath.py来生成PNG的绝对路径。文件夹图标包含PNG文件。

absolutePath.py:

import sys
import os

def absolutePath(relative_path):
    base_path=getattr(sys,'_MEIPASS',os.path.dirname(os.path.abspath(__file__))) 
    return os.path.join(base_path,relative_path)

test.py:

import sys
from PyQt5 import QtCore,QtGui,QtWidgets
from absolutePath import absolutePath


class Ui_MainWindow(QtWidgets.QMainWindow):

    def __init__(self,debugging=False):
        super().__init__()
        self.__setupUi()
        self.__retranslateUi()
        QtCore.QMetaObject.connectSlotsByName(self)
        self.show()

    def __setupUi(self):        
        self.setObjectName('MainWindow')
        self.resize(400,100)
        
        self.centralwidget=QtWidgets.QWidget(self)
        self.centralwidget.setObjectName('centralwidget')
        self.verticalLayout=QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName('verticalLayout')
        self.pushButton=QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setText('')
        icon=QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(absolutePath('Icons/icon.png')),QtGui.QIcon.Normal,QtGui.QIcon.Off)
        self.pushButton.setIcon(icon)
        self.pushButton.setIconSize(QtCore.QSize(32,32))
        self.pushButton.setObjectName('pushButton')
        self.verticalLayout.addWidget(self.pushButton)
        self.setCentralWidget(self.centralwidget)

    def __retranslateUi(self):
        _translate=QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate('MainWindow','MainWindow'))


if __name__=='__main__':
    app=QtWidgets.QApplication(sys.argv)
    uiObj=Ui_MainWindow()
    sys.exit(app.exec())

最后是PyInstaller命令:

python -m PyInstaller --onefile --windowed --add-data Icons\\*.png;Icons\\ test.py

如此生成的可执行文件包括文件夹中图标中的所有PNG 称为图标。这些图片可以在运行时找到并出现。该可执行文件也可以在其他计算机上使用。