如何不使用.qrc文件让QUiLoader加载的UI正常显示图标?
解决PySide5加载.ui文件时本地图标不显示问题(无需.qrc文件)
使用Qt Creator为Python项目制作.ui文件,仅用它做UI编辑,未用其管理整个项目。通过本地文件路径(未用.qrc)添加的图标在Qt Creator中显示正常,但用PySide5.15.2的QUiLoader加载后图标无法显示。
加载代码:
loader = QtUiTools.QUiLoader() ui_file = QtCore.QFile(ui_path) ui_file.open(QtCore.QFile.ReadOnly) form = loader.load(ui_file) ui_file.close()
.ui文件中图标相关XML片段:
... <property name="icon"> <iconset> <normaloff>../../resources/icons/list-add.svg</normaloff>../../resources/icons/list-add.svg</iconset> </property> ...
原因分析
Qt Creator会基于项目根目录解析图标相对路径,但QUiLoader加载时,默认以Python进程的当前工作目录查找文件,且不会自动将.ui中的路径转换为可识别的本地文件图标,导致图标加载失败。
解决方案(无需.qrc及构建步骤)
方法1:加载UI后手动为控件设置图标
适合图标数量较少的场景,直接通过绝对路径构造QIcon并赋值给控件:
from PySide5 import QtUiTools, QtCore, QtGui, QtWidgets loader = QtUiTools.QUiLoader() ui_file = QtCore.QFile(ui_path) ui_file.open(QtCore.QFile.ReadOnly) form = loader.load(ui_file) ui_file.close() # 基于UI文件所在目录构造图标绝对路径 ui_dir = QtCore.QFileInfo(ui_path).absoluteDir() abs_icon_path = ui_dir.filePath("../../resources/icons/list-add.svg") # 替换为实际控件名称 form.pushButton.setIcon(QtGui.QIcon(abs_icon_path))
方法2:自定义QUiLoader自动处理图标
适合多图标场景,重写QUiLoader的createWidget方法,自动为控件设置正确路径的图标:
from PySide5 import QtUiTools, QtCore, QtGui, QtWidgets class CustomUiLoader(QtUiTools.QUiLoader): def __init__(self, ui_path, parent=None): super().__init__(parent) self.ui_dir = QtCore.QFileInfo(ui_path).absoluteDir() def createWidget(self, className, parent=None, name=""): widget = super().createWidget(className, parent, name) # 针对按钮等带icon属性的控件做处理 if isinstance(widget, QtWidgets.QAbstractButton): # 从.ui文件的相对路径构造绝对路径 icon_rel_path = "../../resources/icons/list-add.svg" abs_icon_path = self.ui_dir.filePath(icon_rel_path) widget.setIcon(QtGui.QIcon(abs_icon_path)) return widget # 使用自定义加载器加载UI loader = CustomUiLoader(ui_path) ui_file = QtCore.QFile(ui_path) ui_file.open(QtCore.QFile.ReadOnly) form = loader.load(ui_file) ui_file.close()
注:如果存在多个不同路径的图标,可以解析.ui文件的XML提取路径,或维护一个路径映射表适配所有图标。
方法3:切换Python进程工作目录到项目根目录
让QUiLoader的路径解析逻辑和Qt Creator一致,直接切换工作目录:
import os from PySide5 import QtUiTools, QtCore # 计算项目根目录(示例:UI文件在src/ui下,根目录为UI目录往上两级) ui_abs_path = os.path.abspath(ui_path) project_root = os.path.dirname(os.path.dirname(os.path.dirname(ui_abs_path))) # 切换工作目录到项目根 os.chdir(project_root) # 加载UI文件 loader = QtUiTools.QUiLoader() ui_file = QtCore.QFile(ui_abs_path) ui_file.open(QtCore.QFile.ReadOnly) form = loader.load(ui_file) ui_file.close()
注意:切换工作目录会影响程序中其他文件路径的解析,需确保其他文件操作也适配此目录。
内容的提问来源于stack exchange,提问作者knipknap
相关产品推荐
相关产品推荐

