使用 cx_Freeze 冻结时不显示主窗口图标
Posted
技术标签:
【中文标题】使用 cx_Freeze 冻结时不显示主窗口图标【英文标题】:Main Window Icon Not Displayed when Frozen with cx_Freeze 【发布时间】:2018-10-17 17:14:34 【问题描述】:我想在使用 cx_Freeze 冻结基线后在 PyQt 窗口中显示自定义图标。当从 IDE(对我来说是 Spyder)执行解冻脚本时,该图标显示正常。我正在使用 PyQt5、Python 3.6 和 Windows 10。这是我的 Python 脚本 (IconTest.py
),它创建一个主窗口并显示图标的路径以及该路径是否存在。图标文件需要和IconTest.py
在同一目录下:
import sys, os
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
from PyQt5.QtGui import QIcon
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(200, 300, 600, 100)
if getattr(sys, 'frozen', False): #If frozen with cx_Freeze
self.homePath = os.path.dirname(sys.executable)
else: # Otherwise, if running as a script (e.g., within Spyder)
self.homePath = os.path.dirname(__file__)
self.iconFileName = os.path.join(self.homePath, 'myIcon.ico')
self.setWindowIcon(QIcon(self.iconFileName))
self.setWindowTitle('Icon')
self.label1 = QLabel(self)
self.label2 = QLabel(self)
self.label1.move(10, 20)
self.label2.move(10, 40)
self.label1.setText("Path to icon file: " + str(self.iconFileName))
self.label2.setText("Does file exit? " + str(os.path.exists(self.iconFileName)))
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
这是我在 Spyder(解冻)中运行脚本时的结果。如您所见,显示的图标类似于秒表:
这是我用于创建冻结基线的 setup.py:
from cx_Freeze import setup, Executable
import os, sys
exeDir = os.path.dirname(sys.executable)
platformsPath = os.path.join(exeDir, "Library\\Plugins\\Platforms\\")
iconPath = os.path.join(os.path.dirname(__file__), "myIcon.ico")
exe=Executable(script="IconTest.py", base = "Win32GUI", icon = iconPath)
includes=[iconPath, platformsPath]
excludes=[]
packages=[]
setup(
version = "0.1",
description = "My Icon Demo",
options = 'build_exe': 'excludes':excludes,'packages':packages,'include_files':includes,
executables = [exe]
)
这是我运行冻结脚本时的结果(build
目录中的可执行文件)。如您所见,秒表图标已替换为通用窗口图标:
建议?
【问题讨论】:
您必须改进最初的问题或至少删除它,而不是创建多个具有相同问题的帖子 我标记了另一个问题,供版主删除。我无法删除它,因为它已被回答。问题和回答的方向是错误的,所以我觉得有必要用最少、完整和可行的代码完全重写问题。 图标是否真的被复制到了构建文件夹中? @slalomchip 我已删除我对您其他问题的回答,以便您将其删除。 @Jannick - 是的,图标文件实际上已复制到build
文件夹。否则,窗口中的第二行将是 False
而不是 True
【参考方案1】:
有趣的问题和不错的最小示例。经过一番搜索,我猜这可能与 PyQt5 缺少插件/DLL 以在冻结的应用程序中显示 .ico 图像文件有关。参见例如How to load .ico files in PyQt4 from network.
如果这是真的,你有两个选择:
尝试使用 .png 文件作为窗口图标的相同示例
如果plugins
目录包含在冻结的应用程序中但找不到,请尝试添加以下语句
pyqt_dir = os.path.dirname(PyQt5.__file__)
QApplication.addLibraryPath(os.path.join(pyqt_dir, "plugins"))`
之前
app = QApplication(sys.argv)
在您的主脚本中。见this answer。
如果plugins
目录不包含在冻结的应用程序中,您需要使用build_exe
选项的include_files
条目告诉cx_Freeze
包含它。要么您设法动态地让您的安装脚本将它包含在 PyQt5
正在寻找它的地方,使用 include_files
中的元组 (source_path_to_plugins, destination_path_to_plugins)
,或者您告诉 PyQt5
在哪里寻找它,使用 QApplication.addLibraryPath
.
在您对这个问题的上一个问题中,您实际上有一个条目在您的安装脚本中包含一个Plugins\\Platforms
目录,也许您只需要修复这个包含。请注意,cx_Freeze
版本 5.1.1(当前)和 5.1.0 将所有包移动到 build
目录的 lib
子目录中,与其他版本相反。
【讨论】:
(1) 尝试 PNG 文件没有任何区别。 (2)发现需要添加Platforms
目录。我想我在最小化setup.py
时从未从exe.win-amd64-3.6
目录中删除它。我在上面的问题中更正了脚本。 (3) 我使用的是 cx_Freeze 5.1.1。我认为您可能是正确的,某处缺少 .dll 文件。我尝试了对exe.win-amd64-3.6
目录和lib
目录的不同添加。 Platform
目录必须添加到 exe.win-amd64-3.6
,而不是 lib
。仍在寻找正确的解决方案 - 尚未找到。
@slalomchip 您是否尝试过在设置脚本中使用packages = ['atexit', 'PyQt5']
?
我在安装脚本中包含了packages = ['atexit', 'PyQt5']
,但没有成功。无论PyQt5
是否在packages
列表中,生成的lib
目录中的PyQt5
目录都是相同的(6 个目录中的148 个文件)。我不明白将atexit
添加到package
列表的目的,除非我将atexit
合并到我的图标脚本中(我还没有这样做)。您建议在package
列表中包含atexit
有什么原因吗?仍在搜索。
@slalomchip 更具体地说: 1. 尝试找出在您的 python 安装中哪个 DLL 解释 .ico 图像,它应该类似于 lib\site-packages\PyQt5\Qt\plugins\imageformats\qico.dll
; 2. 检查这个DLL是否被cx_Freeze
包含在生成的lib
目录中,它应该在某个plugins\imageformats
目录中;我的猜测是,将PyQt5
添加到packages
列表会告诉cx_Freeze
包含整个PyQt5
目录; 3. 使用QApplication.addLibraryPath
告诉您的应用程序在哪里可以找到这个plugins
目录。
@slalomchip 我建议在packages
列表中包含atexit
的原因是它是在cx_Freeze
的PyQt5
示例设置脚本中完成的,请参阅lib\site-packages\cx_Freeze\samples\PyQt5
;老实说,我也不明白目的。【参考方案2】:
回答:我一直在使用 Anaconda 平台,并在其他帖子中读到,由于 Anaconda 构建其内容的方式,PyInstaller 和 Anaconda 之间存在问题。考虑到 cx_Freeze 可能存在同样的问题,我在另一台机器上安装了 Python(没有 Anaconda),并从这个新的 Python 安装中冻结了脚本。 该图标按预期出现在冻结脚本中。为了使图标正确显示,我对 setup.py 脚本进行了以下更改:
-
删除
import sys
删除了exeDir = ...
这一行
删除了platformsPath = ...
这一行
从includes =
列表中删除了platformsPath
【讨论】:
【参考方案3】:我遇到了类似的问题并发布了答案here。
基本上,我通过将文件存储在 python 字节数组中并通过 QPixmap 将其加载到 QIcon 中来克服了这个问题。
【讨论】:
以上是关于使用 cx_Freeze 冻结时不显示主窗口图标的主要内容,如果未能解决你的问题,请参考以下文章
使用 cx_Freeze 冻结 Python 3.7 脚本时如何修复错误
使用 cx_Freeze 冻结成可执行文件后如何知道当前文件路径?