Qt Tutorial #5: System zasobów biblioteki Qt.

|

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 🙂

Dodaj komentarz