Images and Resources
Graphic images can be used to add visual impact to various applications. In this section, we show how to build an application or a library that includes graphic images in the project.
Qt 4 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 they can "move" with the executable.
In the next examples, we will demonstrate 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 we wish to use in a Resource Collection File, an XML file that has the extension .qrc. The resource file in libcards2 is automatically generated by a python script. Here is an abbreviated listing of it.
images/qh.png images/qd.png images/jc.png [ ... ] images/jd.png images/ac.png
RCC is a file format, required by qmake and rcc (Qt's resource compiler), that generally consists of a list of elements enclosed by tags. Each element contains a relative path and an optional file alias.
We must add a RESOURCES line in the project file that contains the name of the qresource file, as shown in Example 11.7.
Example 11.7. src/libs/cards2/cards2.pro
# project file for libcards2 include ($$(CPPLIBS)/utils/common.pri) TEMPLATE = lib INCLUDEPATH += . QT += gui # For locating the files. RESOURCES = cards2.qrc SOURCES += cardpics.cpp HEADERS += cardpics.h DESTDIR=$$(CPPLIBS) target.path=$$(CPPLIBS) unix { UI_DIR = .ui MOC_DIR = .moc OBJECTS_DIR = .obj } |
When this project is built, the resource compiler generates an extra file named cards2_qrc.cpp that contains byte arrays defined in C++. This file gets compiled and linked into the project binary (executable or library) instead of the original files. The DESTDIR line specifies that the shared object files for libcards2 will be located in $CPPLIBS with the other libraries that we have built.
In libcards2, we defined a class named CardPics, shown in Example 11.8, which utilizes the QPixmap class. There are three Qt classes that facilitate the handling of images.
- QPixmap designed and optimized for drawing on the screen
- QImage designed for input and output operations and for direct pixel access
- QPicture designed to enable scalability
Example 11.8. src/libs/cards2/cardpics.h
[ . . . . ] class CardPics { public: CardPics(); static CardPics* instance(); QPixmap get(QString card); static const QString values, suits; protected: static QString fileName(QString card); private: QMap m_pixmaps; }; [ . . . . ] |
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, we can use the alias that was 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 :/. Example 11.9 shows some Qpixmaps created with pathnames of this format.
Example 11.9. src/libs/cards2/cardpics.cpp
[ . . . . ] const QString CardPics::values="23456789tjqka"; const QString CardPics::suits="cdhs"; CardPics* CardPics::instance() { static CardPics* inst = 0; if (inst == 0) inst = new CardPics; return inst; } CardPics::CardPics() { foreach (QChar suit, suits) { foreach (QChar value, values) { QString card = QString("%1%2").arg(value).arg(suit); QPixmap pixmap(fileName(card)); m_pixmaps[card]= pixmap; } } } QString CardPics::fileName(QString card) { return QString(":images/%1.png").arg(card); } QPixmap CardPics::get(QString card) { return m_pixmaps[card]; } [ . . . . ] |
Each resource is used to construct a QPixmap, which gets added to CardPics for easy access with the get() function.