11

我有一个 PySide GUI 应用程序(用 Python 3 编写,在 Windows 7 Pro 上运行),我在其中设置应用程序图标如下:

class MyGui(QtGui.QWidget):
    def __init__(self):
        super(MyGui, self).__init__()
        ...
        self.setWindowIcon(QtGui.QIcon('MyGui.ico'))

        if os.name == 'nt':
            # This is needed to display the app icon on the taskbar on Windows 7
            import ctypes
            myappid = 'MyOrganization.MyGui.1.0.0' # arbitrary string
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
        ...

ctypes这个答案中得到了这些东西。如果我删除这些行,那么当我执行python MyGui.py.

包含这些行后,一切看起来都很棒,窗口和任务栏上有正确的图标。但是,当我使用 cxfreeze 打包 gui 时,窗口和任务栏图标都变为通用的 windows .exe 图标。

我正在使用此处cxfreeze.bat的说明打包应用程序,包括开关。使用该开关使生成的 exe 在资源管理器中查看时具有正确的图标。但是,应用程序窗口和任务栏在我启动应用程序时不显示图标。我尝试将 .ico 文件复制到与 .exe 相同的目录,但这没有帮助。--icon

我在 Windows 7 和 8 上都得到了相同的行为。奇怪的是,如果我将应用程序固定到任务栏,任务栏图标会正确显示,但窗口图标仍然是通用的 exe 图标。

如何让图标正确显示?

4

4 回答 4

8

PySide 需要访问一个特殊的 DLL 来读取 .ico 文件。我认为它是 qico4.dll。

您可以尝试更改对 setWindowIcon 的调用以将图标打开为 .png 并将其 .png 放在 ./dist 目录中,看看是否有效。如果是这样,那么您的代码很好,我很确定这是 .dll 问题。您需要告诉 cx_freeze 在构建中包含该 dll。

我认为 PySide 为 Windows 提供了嵌入式 .ico 并且不需要能够读取数据本身,所以这就是它起作用的原因。但是,要读取嵌入的图标资源或可执行目录中的 ico 文件,它需要 DLL。

于 2013-06-12T15:48:41.317 回答
6

我找到了另一个不需要PNG和ICO格式的图标的解决方案。正如西蒙在他的回答中提到的那样,读取 .ico 文件需要qico4.dll 。此外,此文件需要放置在一个名为的目录imageformats中,该目录是您的应用程序目录的子目录。文件夹结构应如下所示:

My Gui
|
|-- MyGui.exe
|-- QtCore4.dll
|-- QtGui4.dll
|-- ...
|
|-- imageformats
    |
    |-- qico4.dll

qico4.dll与您的 PySide 发行版一起安装。如果您选择典型的安装选项,该文件应位于

os.path.join(os.path.dirname(sys.executable), 
             'Lib',
             'site-packages',
             'PySide',
             'plugins',
             'imageformats' )
于 2013-06-13T15:08:41.037 回答
3

我遇到了同样的问题,这就是我解决它的方法。我在 png 文件中有图标(但我想它也适用于其他格式。

首先在 Linux 中,我将图像文件内容转储到具有以下内容的文件中:

hexdump -v -e '"\\x" 1/1 "%02x" ' icon.png > icon.py

然后我将 icon.py 编辑为具有以下格式:

icon = b'hexdump'

例如

icon = b'\xf3\a3'

然后我导入了图标:

from icon import icon

然后我使用以下内容设置图标:

qp = QtGui.QPixmap()
qp.loadFromData(icon)
appIcon = QtGui.QIcon(qp)
self.setWindowIcon(appIcon)

它奏效了。我认为这是最稳健的方式。cx_Freeze不能干涉它。

于 2020-11-17T17:59:22.370 回答
0

根据 Saren Tasciyan 的回答,这是一个跨平台的解决方案:

>>> from pathlib import Path
>>> hex_content = Path('icon.png').read_bytes()
>>> Path('icon.py').write_text(f'icon = {hex_content}')

然后只是:

from icon import icon

pixmap = QtGui.QPixmap()
pixmap.loadFromData(icon)
appIcon = QtGui.QIcon(pixmap)
self.setWindowIcon(appIcon)
于 2022-01-23T21:01:49.477 回答