如何在 macOS 的 Python 3 Qt6 应用中从文件设置应用图标?
可以直接从图片文件创建 QIcon,再调用 app.setWindowIcon(icon) 设置应用图标,无需编译或嵌入图片。要为某个 QMainWindow 单独设置图标,可以调用 window.setWindowIcon(icon),该方法继承自 QWidget。Qt 应用图标 API、QWidget.windowIcon
在 macOS 上,还要区分程序运行时的 Dock 图标、窗口标题栏图标和 Finder 中的应用图标,它们的显示规则不同。
为什么创建 QIcon 后没有变化?
QIcon 保存图标数据。创建对象或向其中添加图片后,还需要将它传给应用或窗口的设置方法,才能将其设为图标。
问题中提到使用 addIcon 加载文件。对于标准 QIcon,可以用 addFile() 从文件添加图片,也可以直接使用 QIcon(filename)。创建 QIcon 前应先创建 QApplication。QIcon 文档
直接运行 .py 脚本的示例
问题没有说明使用的是 PySide6 还是 PyQt6。下面以 PySide6 为例,将 app.png 放在脚本旁边:
my_tool/
├── main.py
└── app.png
main.py:
import sys
from pathlib import Path
from PySide6.QtGui import QIcon
from PySide6.QtWidgets import QApplication, QMainWindow
def main():
app = QApplication(sys.argv)
icon_path = Path(__file__).resolve().parent / "app.png"
if not icon_path.is_file():
raise FileNotFoundError(f"Icon file not found: {icon_path}")
icon = QIcon(str(icon_path))
if icon.pixmap(64, 64).isNull():
raise RuntimeError(f"Cannot decode icon file: {icon_path}")
app.setWindowIcon(icon)
window = QMainWindow()
window.setWindowTitle("My Tool")
window.resize(640, 400)
window.show()
return app.exec()
if __name__ == "__main__":
sys.exit(main())
如果使用 PyQt6,将两行 Qt 导入替换为:
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QApplication, QMainWindow
如果某个窗口需要单独的图标,在 window.show() 前调用:
window.setWindowIcon(icon)
也可以先创建空图标,再添加文件:
icon = QIcon()
icon.addFile(str(icon_path))
app.setWindowIcon(icon)
示例使用基于 __file__ 的路径,避免从其他目录启动脚本时找不到图片。QIcon("app.png") 中的相对路径按运行时工作目录解析,该目录不一定是脚本所在目录。
QIcon 可能延迟加载文件,仅检查 icon.isNull() 不足以确认图片能否正常解码,因此示例还检查了生成的 pixmap。QIcon 文件加载说明
macOS 上需要注意什么?
运行时 Dock 图标
直接运行脚本时,在创建 QApplication 后、显示窗口前设置应用图标。运行时设置有时机限制:代码执行到设置图标的语句之前,Dock 的启动弹跳动画可能已经显示默认图标。Qt 的 macOS 应用图标说明
窗口标题栏图标
macOS 的窗口图标用于表示当前文档,通常需要同时通过 setWindowFilePath() 设置文件路径才会显示。因此,标题栏没有出现图标,并不能据此判断应用图标设置失败。只有窗口确实代表某个文件时,才需要考虑文档图标。QWidget.windowIcon 的 macOS 说明
Finder 和启动前的应用图标
setWindowIcon() 不会修改 .py 文件在 Finder 中的图标。
如果以后需要让独立应用在 Finder 和启动阶段都显示自定义图标,可以将脚本封装为 .app,在应用包中提供 .icns 文件,并在 Info.plist 中通过 CFBundleIconFile 关联它。这属于 macOS 应用包配置,具体步骤取决于使用的打包工具,无需为此将 Python 源码改写成 C++。Qt 的 macOS 应用包图标配置
备注:内容仅供参考。
