使用 cx_Freeze 冻结时主 Window 图标不显示
Main Window Icon Not Displayed when Frozen with cx_Freeze
我想在使用 cx_Freeze 冻结基线后在 PyQt window 中显示自定义图标。当从 IDE(对我来说是 Spyder)中执行解冻脚本时,该图标显示正常。我正在使用 PyQt5、Python 3.6 和 Windows 10。这是我的 Python 脚本 (IconTest.py
),它创建一个主 window 并显示路径到图标以及路径是否存在。图标文件需要和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
目录中的可执行文件)时的结果。如您所见,秒表图标已替换为通用 windows 图标:
建议?
有趣的问题和很好的最小示例。经过一番搜索后,我猜想这可能与 PyQt5 缺少 plugin/DLL 以在冻结的应用程序中显示 .ico 图像文件有关。参见例如How to load .ico files in PyQt4 from network.
如果这是真的,您有 2 个选择:
使用 .png 文件作为 window 图标尝试相同的示例
如果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
子目录中,与其他版本相反。
答案: 我一直在使用 Anaconda 平台,并在其他帖子中读到,由于 Anaconda 构建其内容的方式,PyInstaller 和 Anaconda 之间存在问题。考虑到 cx_Freeze 可能存在同样的问题,我在另一台机器上安装了 Python(没有 Anaconda),并冻结了这个新 Python 安装的脚本。
该图标按预期出现在冻结的脚本中。为了使图标正确显示,我对 setup.py 脚本进行了以下更改:
- 已移除
import sys
- 删除了行
exeDir = ...
- 删除了行
platformsPath = ...
- 已从
includes =
列表中删除 platformsPath
我遇到了类似的问题并发布了一个答案here。
基本上,我通过将文件存储在 python 字节数组中并通过 QPixmap 将其加载到 QIcon 中来解决这个问题。
我想在使用 cx_Freeze 冻结基线后在 PyQt window 中显示自定义图标。当从 IDE(对我来说是 Spyder)中执行解冻脚本时,该图标显示正常。我正在使用 PyQt5、Python 3.6 和 Windows 10。这是我的 Python 脚本 (IconTest.py
),它创建一个主 window 并显示路径到图标以及路径是否存在。图标文件需要和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
目录中的可执行文件)时的结果。如您所见,秒表图标已替换为通用 windows 图标:
建议?
有趣的问题和很好的最小示例。经过一番搜索后,我猜想这可能与 PyQt5 缺少 plugin/DLL 以在冻结的应用程序中显示 .ico 图像文件有关。参见例如How to load .ico files in PyQt4 from network.
如果这是真的,您有 2 个选择:
使用 .png 文件作为 window 图标尝试相同的示例
如果
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
子目录中,与其他版本相反。
答案: 我一直在使用 Anaconda 平台,并在其他帖子中读到,由于 Anaconda 构建其内容的方式,PyInstaller 和 Anaconda 之间存在问题。考虑到 cx_Freeze 可能存在同样的问题,我在另一台机器上安装了 Python(没有 Anaconda),并冻结了这个新 Python 安装的脚本。 该图标按预期出现在冻结的脚本中。为了使图标正确显示,我对 setup.py 脚本进行了以下更改:
- 已移除
import sys
- 删除了行
exeDir = ...
- 删除了行
platformsPath = ...
- 已从
includes =
列表中删除platformsPath
我遇到了类似的问题并发布了一个答案here。
基本上,我通过将文件存储在 python 字节数组中并通过 QPixmap 将其加载到 QIcon 中来解决这个问题。