PySide GUI中的应用程序图标

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时,任务栏中会显示Python图标。

包含这些代码行后,一切看起来都很好,窗口和任务栏都有正确的图标。然而,当我使用cxfreeze打包gui时,窗口和任务栏图标都变成了Windows通用的.exe图标。

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

我在Windows 7和8上遇到了同样的问题。奇怪的是,如果我将应用程序固定到任务栏,任务栏图标就会正确显示,但窗口图标仍然是通用的.exe图标。

如何才能使图标正确地显示?

4个回答

8
PySide需要访问一个特殊的DLL文件来读取.ico文件,我认为它是qico4.dll。你可以尝试将setWindowIcon的调用更改为打开.png格式的图标,并将其放置在./dist目录中,看看是否有效。如果有效,则您的代码没有问题,我相信这是.dll文件的问题。您需要告诉cx_freeze将dll文件包含在构建中。我认为PySide向Windows提供嵌入式.ico文件并不需要自己读取数据,所以这就是为什么它能正常工作的原因。但是,要读取嵌入的图标资源或可执行目录中的ico文件,它需要该DLL文件。

太好了!非常感谢。我确实看到一些关于需要qico4.dll的信息,但是关于放置它的解决方案却各不相同,而我尝试过的几个解决方案都没有起作用。将图标同时保存为.ico和.png格式并不是最好的解决方案,但这是解决问题最简单的方法。 - Praetorian

6

我发现了另一种解决方案,它不需要将图标同时保存为PNG和ICO格式。就像Simon在他的回答中提到的那样,读取.ico文件需要使用qico4.dll。此外,需要将此文件放置在名为imageformats的目录中,该目录是应用程序目录的子目录。文件夹结构应该如下所示:

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

您的PySide发行版中已安装qico4.dll。如果您选择典型的安装选项,该文件应位于以下位置:

os.path.join(os.path.dirname(sys.executable), 
             'Lib',
             'site-packages',
             'PySide',
             'plugins',
             'imageformats' )

4

我遇到了同样的问题,这是我解决它的方法。我把图标保存在一个png文件中(但我想其他格式也能行)。

首先,在Linux中,我使用以下命令将图像文件的内容导出到文件中:

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

然后我编辑了 icon.py 文件,使其具有以下格式:

icon = b'hexdump'

e.g.

icon = b'\xf3\a3'

然后我使用以下命令导入图标:

from icon import icon

然后我使用以下代码设置图标:

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

它运行了。我认为这是最健壮的方式。cx_Freeze 不能干扰它。


我不得不稍微修改一下语法:hexdump -v -e '"\\\x" 1/1 "%02x" ' icon.png > icon.py这对我起了作用。 - Michael Podrybau

1

根据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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接