System zasobów biblioteki Qt.
W przypadku prawie każdego programu zachodzi potrzeba dostarczenia, wraz z plikiem wykonywalnym, dodatkowych zasobów.
Dobrym przykładem są obrazy wykorzystywane w graficznym interfejsie użytkownika. Możemy oczywiście dostarczać obrazy jako część instalatora, który rozpakuje je podczas instalacji do katalogu aplikacji. Ma to jednak swoje wady: jest dość uciążliwe i może nie wyglądać profesjonalnie.
Na szczęście w przypadku biblioteki Qt istnieje niezależna od platformy alternatywa – tzw. system zasobów. Pozwala on agregować i łąćzyć dodatkowe zasoby z plikiem wykonywalnym aplikacji. Skutkuje to co prawda zwiększoną wagą pliku wynikowego, ale równocześnie powoduje, że musimy dostarczyć użytkownikowi tylko jeden element – plik wykonywalny.
Jak to działa ?
Do projektu aplikacji możemy dołączyć pliki o rozszerzeniu *.qrc, które opisują zawartość zasobów – jest to po prostu lista ścieżek do plików, zapisana w formacie wykorzystującym składnię XML.
W tym miejscu powinien się pojawić dobry przykład. Trochę skrócimy sobie drogę i wykorzystamy kod, stworzony przy okazji trzeciej części tutoriala. Jeśli nie mieliście okazji przerobić tamtej części – po prostu to zróbcie 🙂
Wynikowo mamy więc projekt z jednym plikiem źródłowym (main.cpp) o następującej treści:
#include <QApplication>
#include <QPushButton>
#include <QMainWindow>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication program(argc, argv);
QMainWindow window;
window.setGeometry(100, 100, 500, 400);
window.setWindowTitle("Okno Główne");
QPushButton button("Zamknij", &window);
button.setGeometry(200, 350, 100, 40);
QLabel label("Tekst etykiety :)", &window);
label.setGeometry(200, 150, 400, 50);
QObject::connect(&button, SIGNAL(clicked()), &program, SLOT(quit()));
window.show();
return program.exec();
}
Aby dodać plik zasobów do projektu, klikamy prawym przyciskiem myszy na nazwę projektu i wybieramy z listy Add New…->Qt->Qt Resource File i klikamy Choose…. Następnie podajemy nazwę pliku – np. resources – i klikamy na Next > oraz Finish.
Zanim dodamy zasoby do naszego pliku, musimy mieć coś ciekawego na dysku 🙂 Tworzymy folder images (w naszym folderze projektowym), do którego kopiujemy plik exit.png. Można go zapisać stąd:
![]()
Wracamy do pliku resources.qrc i w dolnej części QtCreator’a klikamy Add->Add Prefix. Jako nazwę prefixu proponuję ustawić jedynie jeden prawy ukośnik (/). Teraz możemy w tym samym miejscu wybrać Add->Add Files i wskazać pliki w naszym folderze images. Jak widzimy w górnej części okna, QtCreator dodał nasz jedyny plik do pliku zasobów.
W następnym kroku zapisujemy zmiany i wracamy do pliku main.cpp.
Kluczowa zmiana w main.cpp.
Na początku funkcji main dodajemy następującą linię:
Q_INIT_RESOURCE(resources);
Makro Q_INIT_RESOURCE za za zadanie włączenie zasobów do pliku wykonywalnego. Jako parametr podajemy nazwę pliku zasobów, bez rozszerzenia.
Teraz możemy skorzystać z dodanych do projektu zasobów – ustawimy ikonę dla przycisku Zamknij. Obiektowi klasy QPushButton można ustawić nie tylko tekst, ale również dowolną ikonę. Finalnie plik main.cpp wygląda tak:
#include <QApplication>
#include <QPushButton>
#include <QMainWindow>
#include <QLabel>
#include <QIcon>
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(resources);
QApplication program(argc, argv);
QMainWindow window;
window.setGeometry(100, 100, 500, 400);
window.setWindowTitle("Okno Główne");
QPushButton button("Zamknij", &window);
button.setGeometry(200, 350, 100, 40);
button.setIcon(QIcon(":/images/exit.png"));
QLabel label("Tekst etykiety :)", &window);
label.setGeometry(200, 150, 400, 50);
QObject::connect(&button, SIGNAL(clicked()), &program, SLOT(quit()));
window.show();
return program.exec();
}
Po utworzeniu przycisku i ustawieniu jego położenia oraz rozmiarów, ustawiamy dla niego ikonę za pomocą funkcji setIcon. Za pomocą tej funkcji możemy ustawiać ikony dla wszelkiego rodzaju okien, przycisków, umieszczać je na pasku narzędzi i w menu aplikacji. Funkcja setIcon przyjmuje jako argument obiekt klasy QIcon – tutaj jawnie tworzymy taki obiekt, jako parametr konstruktora podając „:/images/exit.png” – ścieżkę do pliku ikony.
Dwukropek jest tutaj kluczowy. Dwukropek na początku ścieżki mówi konstruktorowi klasy QIcon, że pliku ikony ma szukać w zasobach aplikacji, a nie na dysku.
Oto efekt naszego kodu po uruchomieniu aplikacji:

Jak widać, system zasobów w bibliotece Qt jest bardzo intuicyjny.
Resource Compiler
Należy w tym miejscu wspomnieć o narzędziu, które umożliwia nam całą tę operację, związaną z wygodnym dodawanie zasobów do pliku wykonywalnego. To narzędzie to RCC (Resource Compiler) – tzw. kompilator zasobów. Generuje on dodatkowe pliki źródłowe, zawierające zasoby wymienione w plikach *.qrc. Wewnętrznie wygląda to tak, że zasoby są zapisywane w postaci binarnej i dołączane do pliku wykonywalnego aplikacji. Oczywiście dla nas wszystko dzieje się w pełni automatycznie, a my widzimy tylko (lub aż) ostateczny rezultat.
Na koniec chciałbym jeszcze pokazać, jak wygląda treść naszego pliku resources.qrc (jest to de facto zwykły plik tekstowy):
<RCC>
<qresource prefix="/">
<file>images/exit.png</file>
</qresource>
</RCC>
Jak widać, składnia takiego pliku jest dość prosta i można bez problemu edytować go w dowolnym edytorze tekstu. Ja polecam jednak korzystać z dobrodziejstw narzędzi które dostajemy – w tym przypadku mamy niezawodnego QtCreator’a, który integruje system zasobów w ramach swoich funkcjonalności 🙂