Programowanie C++ Qt4 w systemie Gnu-Linux/Helo World w QT4

Hello World w QT

Aplikacja GUI

edytuj

Stos a sterta

edytuj

W języku C++ mamy dwie możliwości tworzenia obiektów.

  1. Tworzenie obiektów na stosie
  2. 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

edytuj

Poniż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

edytuj

 

Tak będziemy pisać programy w dalszej części

edytuj

W 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

edytuj

Taka 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;