9.5.  Icons, Images and Resources

[ fromfile: resources.xml id: resources ]

You can use graphic images to add visual impact to an application. In this section, we show how to build an application or a library that includes graphic images in the project.

Qt enables projects to make use of binary resources, such as images, sounds, icons, text in some exotic font, and so forth. Resources such as these are generally stored on disk in separate binary files. The advantage of incorporating binary dependencies in the actual project is that they can then be addressed using paths that do not depend on the local file system, and are deployed automatically with the executable.

Qt provides at least two ways to get standard icons. One is from the desktop style QStyle::standardIcon(), another is from pluginable icon themes: QIcon::fromTheme(). But you might want to use additional icons from other sources.

The next examples show how to create and reuse a library that includes images, one for each card in a deck of playing cards.

The first step is to list the binary files you want to use in a resource collection file, an XML file that has the extension .qrc. A piece of the resource file in libcards2 is shown below.

 
<!DOCTYPE RCC>
<RCC version="1.0"><qresource>
<file alias="images/qh.png">images/qh.png</file>
<file alias="images/qd.png">images/qd.png</file>
<file alias="images/jc.png">images/jc.png</file>
<file alias="images/js.png">images/js.png</file>
[...]
</qresource>
</RCC>

[Tip] QtCreator and qrc Files

Among other things, QtCreator, the Nokia open source Qt-based IDE, is an editor of qrc files, as shown in Figure 9.11. You can create new (or edit existing) resource files and add or modify resources using GUI forms and file choosers to ensure that they contain what you want.

Provided the .qrc file is added to your .pro file, and you are in QtCreator, you can access the resources from the [...] button in the property editor for any property that can be set to a resource.

Figure 9.11.  QtCreator Resource Editor

QtCreator Resource Editor

qrc is an XML file format, used by qtcreator and rcc (Qt's resource compiler), that generally consists of a list of <file> elements enclosed by <qresource> tags. Each <file> element contains a relative path and an optional file alias.

Add a RESOURCES line in the project file that contains the name of each qresource file, as shown in Example 9.4.

Example 9.4. src/libs/cards2/cards2.pro

include (../libs.pri)

TEMPLATE = lib
QT += gui

# For locating the files.
RESOURCES = cards2.qrc
SOURCES += cardpics.cpp \
    card.cpp
HEADERS += cardpics.h \
    card.h \
    cards_export.h

win32 {
        DEFINES += CARDS_DLL
}

<include src="src/libs/cards2/cards2.pro" href="src/libs/cards2/cards2.pro" id="cardspro" mode="txt"/>


When this project is built, rcc generates an extra file named cards2_qrc.cpp that contains byte arrays defined in C++. This file is compiled and linked into the project binary (executable or library) instead of the original card image files. The DESTDIR line specifies that the shared object files for libcards2 will be located in $CPPLIBS with the other libraries that you have built.

Attaching required binary data files to projects as resources makes the project more robust. The source code does not need to use nonportable pathnames for the resource files. To refer to a file that is stored as a resource, you can use the alias established in the .rcc file, and precede it with the prefix, :/. Each resource then appears (to Qt) to be located in a private virtual file system, rooted at :/. These benefits do come with a cost, however. The executable is larger, and the program requires more memory.

In libcards2, you have a class named CardPics, which provides QImages of cards in a convenient way. Example 9.5 shows some images created with pathnames of this format.

Example 9.5. src/libs/cards2/cardpics.cpp

[ . . . . ]
const QString CardPics::values="23456789tjqka";
const QString CardPics::suits="cdhs";

CardPics::CardPics(QObject* parent) : QObject(parent) {
    foreach (QChar suit, suits) {
        foreach (QChar value, values) {
            QString card = QString("%1%2").arg(value).arg(suit);
            QImage image(fileName(card));
            m_images[card]= image;
        }
    }
}

QString CardPics::fileName(QString card) {
    return QString(":/images/%1.png").arg(card);   1
}
QImage CardPics::get(QString card) const {
   return m_images.value(card.toLower(), QImage());
}
[ . . . . ]

1

From resource

<include src="src/libs/cards2/cardpics.cpp" href="src/libs/cards2/cardpics.cpp" id="cardpicscpp" mode="cpp"/>


There are three Qt classes that facilitate the handling of images.

In libcards2, each QImage is constructed in advance from a resource, and added to CardPics for quick access with the get() function.