Programowanie C++ Qt4 w systemie Gnu-Linux/Helo World w QT4
Hello World w QT
Aplikacja GUI
edytujStos a sterta
edytujW języku C++ mamy dwie możliwości tworzenia obiektów.
- Tworzenie obiektów na stosie
- Dynamiczne tworzenie obiektów w zapasie pamięci komputera tzw. stercie. Pamięć dla obiektu jest przydzielana za pomocą operatora "new".
Obiekt na stosie
edytuj#include <QApplication>
#include <QLabel>
//
int main(int argc, char ** argv) // 1
{
QApplication app( argc, argv ); // 2
//tworzenie obiektu typu Qlabel na stosie
QLabel label;
//wywołanie metody settekst do ustawienia napisu
label.setText("Hello world QT");
//zwiększenie rozmiaru do 90/40 pixeli
label.resize(90,40);
//rysowanie labela
label.show();
return app.exec();
}
Wywołanie
QLabel label;
jest stworzeniem obiektu o nazwie label a obiekt ten jest typu (klasy) Qlabel.
Tworzeniu obiektów w języku C++ zawsze towarzyszy domyśle uruchomienie konstruktora. Zadaniem tej specjalnej funkcji jest inicjalizacja obiektu. W pokazanym przykładzie konstruktora nie są przekazywane żadne argumenty. To dlatego, że klasa Qlabel została wyposażona w konstruktor z domniemanymi parametrami zerowymi. O tym jakich parametrów wymaga konstruktor możemy się dowiedzieć czytając dokumentację klasy http://qt-project.org/doc/qt-4.8/qlabel.html.
QLabel ( QWidget * parent = 0, Qt::WindowFlags f = 0 )
QLabel ( const QString & text, QWidget * parent = 0, Qt::WindowFlags f = 0 )
Ps.
Na uwagę zasługuje wywołanie QApplication app( argc, argv ); Również i tu mamy do czynienia z tworzeniem obiektu app klasy QApplication. Jednakże tutaj do konstruktora trafiają dwa argumenty z funkcji main. Wiąże się to z tym, że konstruktor wspiera polecenia wydawane z konsoli gdzie argc to liczba argumentów argv to wskaźnik na tablice argumentów w postaci stringów.
int main(int argc, char ** argv)
Jak czytać taką deklarację char ** argv?? argv jest wskaźnikiem do wskaźnika na typ char. Ponieważ wskaźnik na typ char jest po prostu napisem. Dlatego argv traktujemy jako wskaźnik do tekstu. A właściwie do tablicy tekstów. Dlatego zamiennie możemy napisać tak
int main(int argc, char *argv[])
Bo z klasycznego C wiemy, że tablica to po prostu wskaźnik na pierwszy element. Dlatego ta druga deklaracja jest o wiele bardziej czytelna
Obiekt na stercie
edytujPoniżej przedstawiam drugie podejście do programowania oczywiście plik wynikowy posiada mniejszy rozmiar a wiąże się to z tym, iż obiekty są tworzone dynamicznie
#include <QApplication>
#include <QLabel>
//
int main(int argc, char ** argv)
{
QApplication* app= new QApplication(argc, argv);
//tworzenie obiektu na stercie typu QLabel - zmienna label będzie wskaźnikiem na ten obiekt
QLabel *label =new QLabel();
//wywołanie metody settekst do ustawienia napisu (wyłuskanie z pod wskaźnika)
label->setText("Hello world QT");
//zwiększenie rozmiaru do 90/40 pixeli
label->resize(90,40);
//rysowanie labela
label->show();
return app->exec();
delete label;
delete app;
}
Jeśli operator new przydziela pamięć i wywołuje konstruktor, to operator delete działa w drugą stronę. Operator wywołuje destruktor i zwalnia pamięć, która została przydzielona dla obiektu ze sterty. Jeśli tego nie zrobimy będziemy mieli wycieki pamięci w naszym programie. Jak się później okaże twórcy biblioteki zadbali o to aby nie było konieczne usuwanie obiektów klasy QT. Jeśli obiekt posiada właściciela to destruktor właściciela zajmie się usuwaniem potomków.
Wynik działania programu
edytujTak będziemy pisać programy w dalszej części
edytujW Qt nie musimy się martwić o stosowanie operatora delete do obiektów klasy QT jeśli zastosujemy się do poniższego schematu pisania programów
- Tworzymy obiekt klasy QObject (lub innej która dziedziczy po QObject ) na stosie. Obiekt będzie rodzicem
- W obiektach tworzonych dynamicznie których klasy dziedziczą po QObject podajemy jako parametr parent adres do rodzica przy pomocy referencji.
#include <QApplication>
#include <QLabel>
//
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
QWidget rodzic;
rodzic.resize(110,30);
rodzic.show();
QLabel *label =new QLabel("ala ma trzy koty",&rodzic);
label->show();
return app.exec();
}
W ten sposób zapewniamy sobie automatyczne niszczenie obiektów klasy QT wraz z zamknięciem programu
Plik .pro projektu QT
edytujTaka dygresja. Aby obiekt się odpowiednio skompilował poprzez polecenie Qmake musi posiadać odpowiednie informacje i co najważniejsze podłączone biblioteki QT.
#------------------------------------------------- # # Project created by QtCreator 2014-08-13T11:47:41 # #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = untitled TEMPLATE = app SOURCES += main.cpp HEADERS += FORMS +=
Ważne są wpisy QT += core gui widgets jest to dołączenie odpowiednich bibliotek QT - informacja dla linkera. Np bez wpisu widgets kompilacja się wysypie już przy wywoływaniu
QLabel label;