Hypergraphe Hypergraphe - 1 year ago 205
Python Question

QIcon.fromTheme not displaying icon in PyQt

I am having troubles to display the icon of a QAction selected from the current icon theme. I made the ui with Qt designer and exported it with

pyuic4 sample.ui > sample.py
. After setting the icon from the theme with
, I get the following source code :

from PyQt4 import QtCore, QtGui
import sys

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

class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.toolBar = QtGui.QToolBar(MainWindow)
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
self.actionSample = QtGui.QAction(MainWindow)


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

When I execute it, the toolbar does not display the icon 'document-open'. Is it a bug or am I doing something wrong ?


Answer Source

The icon lookup process used by QIcon.fromTheme is somewhat complex.

Icon themes are only directly supported on the X11 platform for the GNOME and KDE desktop environments. For other platforms/desktops, it will be necessary to either install a theme along with the application, or tweak the user's environment in various ways.

To find the current system theme for GNOME, Qt will query gconf (if the gtk style is available), and otherwise default to the "gnome" theme. For KDE, Qt will examine the kdeglobals settings file(s), and otherwise default to "oxygen" (or "crystalsvg" for earlier versions of KDE). In addition, the "hicolor" theme can always be used as a fallback.

Once the system theme name has been determined, Qt will look for the directory containing the icons in various pre-determined places, which again depend on both the platform and desktop being used. On X11, this includes $HOME/.icons and $XDG_DATA_DIRS/icons. The only location common to all platforms/desktops is the resource path :/icons.

Icon theme directories must include an index.theme file, which (amongst other things) specifies the subdirectories that can contain icons. Only icon files with a png or svg extension are used.

The QIcon class has some static methods which will show exactly where Qt is looking for themed icons:

>>> from PyQt4 import QtGui
>>> app = QtGui.QApplication([])
>>> for path in QtGui.QIcon.themeSearchPaths():
...     print "%s/%s" % (path, QtGui.QIcon.themeName())

If the "document-open" icon isn't being displayed, Qt is either looking in the "wrong" place, or the icon is missing altogether.


As I said above: by default, Qt only supports GNOME and KDE on the X11 platform. It doesn't know anything about FluxBox WM, and so cannot detect the current icon theme. This means it will fall back to using a minimal "hicolor" theme, which may not have all the required icons.

One way to solve this issue, is to create a "hicolor" symlink that points to the theme you want to use. Ideally, this should go in the location that is first in Qt's list of search paths:

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


Qt5 still only supports kde and gnome by default, but the Qt Platform Abstraction layer at least makes it possible to create custom theme plugins (LXQT is one desktop environment that takes advantage of this). There are also several more DE's that are now treated as gtk/gnome: X-CINNAMON, UNITY, MATE, XFCE and LXDE.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download