QIcon.fromTheme не отображает значок в PyQt

У меня возникают проблемы с отображением значка QAction, выбранного из текущей темы значка. Я сделал ui с дизайнером Qt и экспортировал его с помощью pyuic4 sample.ui > sample.py. После установки значка из темы с помощью self.actionSample.setIcon(QtGui.QIcon.fromTheme(_fromUtf8("document-open"))), я получаю следующий исходный код:

from PyQt4 import QtCore, QtGui
import sys

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(800, 600)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)
        self.toolBar = QtGui.QToolBar(MainWindow)
        self.toolBar.setObjectName(_fromUtf8("toolBar"))
        MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
        self.actionSample = QtGui.QAction(MainWindow)
        self.actionSample.setObjectName(_fromUtf8("actionSample"))
        self.actionSample.setIcon(QtGui.QIcon.fromTheme(_fromUtf8("document-open")))
        self.toolBar.addAction(self.actionSample)

        QtCore.QMetaObject.connectSlotsByName(MainWindow)

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(window)
    window.show()
    app.exec_()

Когда я его выполню, на панели инструментов не отображается значок "document-open". Это ошибка или я что-то не так?

Спасибо

Ответ 1

Процесс поиска значков, используемый QIcon.fromTheme, несколько сложный.

Темы значков поддерживаются непосредственно на платформе X11 для рабочих сред GNOME и KDE. Для других платформ/рабочих столов потребуется либо установить тему вместе с приложением, либо настроить пользовательскую среду различными способами.

Чтобы найти текущую системную тему для GNOME, Qt будет запрашивать gconf (если доступен стиль gtk), и в противном случае по умолчанию используется тема "gnome". Для KDE Qt рассмотрит файлы настроек kdeglobals, а в ином случае по умолчанию - "кислород" (или "кристаллы" для более ранних версий KDE). Кроме того, тема "hicolor" всегда может использоваться как резерв.

Как только имя системной темы определено, Qt будет искать каталог, содержащий значки в разных заранее определенных местах, которые снова зависят от используемой платформы и рабочего стола. В X11 это включает $HOME/.icons и $XDG_DATA_DIRS/icons. Единственным местом, общим для всех платформ/настольных компьютеров, является путь ресурса :/icons.

Каталоги каталогов тем должны включать файл index.theme, который (среди прочего) определяет подкаталоги, которые могут содержать значки. Используются только файлы значков с расширением png или svg.

В классе QIcon есть несколько статических методов, которые точно показывают, где Qt ищет тематические значки:

>>> from PyQt4 import QtGui
>>> app = QtGui.QApplication([])
>>> for path in QtGui.QIcon.themeSearchPaths():
...     print "%s/%s" % (path, QtGui.QIcon.themeName())
... 
/home/ekhumoro/.icons/hicolor
/usr/local/share/icons/hicolor
/usr/share/icons/hicolor
:/icons/hicolor

Если значок "открыть документ" не отображается, Qt либо ищет "неправильное" место, либо значок вообще отсутствует.

UPDATE:

Как я уже говорил выше: по умолчанию Qt поддерживает только GNOME и KDE на платформе X11. Он ничего не знает о FluxBox WM и поэтому не может обнаружить текущую тему значка. Это означает, что он вернется к использованию минимальной темы "hicolor" , у которой могут не быть всех необходимых значков.

Один из способов решения этой проблемы - создать символическую ссылку "hicolor" , которая указывает на тему, которую вы хотите использовать. В идеале это должно идти в месте, которое является первым в списке поиска Qt:

$ ln -s icon/theme/directory $HOME/.icons/hicolor

ОБНОВЛЕНИЕ 2:

Qt5 по-прежнему поддерживает kde и gnome по умолчанию, но Уровень абстракции платформы Qt по крайней мере позволяет создавать настраиваемые плагины темы (LXQT - это одна среда рабочего стола, которая использует это). Есть еще несколько DE, которые теперь рассматриваются как gtk/gnome: X-CINNAMON, UNITY, MATE, XFCE и LXDE.