Pierwsze kroki w programowaniu z Qt/pl: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
 
No edit summary
Line 1: Line 1:
=Pierwsze kroki w programowaniu z Qt=
h1. Pierwsze kroki w programowaniu z Qt


Witamy w świecie Qt wieloplatformowego zestawu narzędzi i bibliotek do tworzenia aplikacji z graficznym interfejsem użytkownika (<span class="caps">GUI</span>) i nie tylko. Nauczymy cię tutaj podstaw Qt pokazując jak zaimplementować prostą aplikację typu Notatnik. Po lekturze tego przewodnika powinieneś być gotów do zagłębienia się w dokumentację <span class="caps">API</span> oraz omówień poszczególnych modułów i rozwiązań dostępnych w Qt. Znajdywanie informacji potrzebnych do stworzenia aplikacji, którą zapewne od dawna planujesz napisać, będzie wówczas przebiegać sprawniej.
Witamy w świecie Qt - wieloplatformowego zestawu narzędzi i bibliotek do tworzenia aplikacji z graficznym interfejsem użytkownika (GUI) i nie tylko. Nauczymy cię tutaj podstaw Qt pokazując jak zaimplementować prostą aplikację typu Notatnik. Po lekturze tego przewodnika powinieneś być gotów do zagłębienia się w dokumentację API oraz omówień poszczególnych modułów i rozwiązań dostępnych w Qt. Znajdywanie informacji potrzebnych do stworzenia aplikacji, którą zapewne od dawna planujesz napisać, będzie wówczas przebiegać sprawniej.


==Powitalny notatnik==
== Powitalny notatnik ==


W pierwszym przykładzie stworzymy i pokażemy pole edycji tekstu w jego własnym oknie. Jest to najprostszy możliwy program napisany w Qt posiadający <span class="caps">GUI</span>.
W pierwszym przykładzie stworzymy i pokażemy pole edycji tekstu w jego własnym oknie. Jest to najprostszy możliwy program napisany w Qt posiadający GUI.


[[Image:gs1.png|screenshot]]
[[Image:http://doc.qt.nokia.com/latest/images/gs1.png|screenshot]]


Tak wygląda kod owej aplikacji:
Tak wygląda kod owej aplikacji:


Prześledźmy go linijka po linijce. W dwóch pierwszych dołączamy pliki nagłówkowe [http://doc.qt.nokia.com/latest/qapplication.html QApplication] ''[doc.qt.nokia.com]'' i [http://doc.qt.nokia.com/latest/qtextedit.html QTextEdit] ''[doc.qt.nokia.com]'', czyli dwóch klas, których użyjemy w tym przykładzie. Wszystkie klasy Qt posiadają pliki nagłówkowe ####### tak samo jak ##### klas, których dotyczą.
<code><br />#include &lt;QApplication&amp;gt;<br />#include &lt;QTextEdit&amp;gt;


W 6 linijce tworzony jest obiekt typu [http://doc.qt.nokia.com/latest/qapplication.html QApplication] ''[doc.qt.nokia.com]''. Zarządza on zasobami aplikacji i jest niezbędny do uruchomienia jakiegokolwiek programu Qt mającego <span class="caps">GUI</span>. Parametry argv i args są wymagane, ponieważ każda aplikacja Qt obsługuje zestaw opcji, które można przekazać do programu z linii poleceń (np. -graphicssystem).
int main(int argv, char *'''args)<br />{<br /> QApplication app(argv, args);
<br /> QTextEdit textEdit;<br /> textEdit.show();
<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}<br /></code>
<br />Prześledźmy go linijka po linijce. W dwóch pierwszych dołączamy pliki nagłówkowe &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/latest/qapplication.html i &quot;QTextEdit&amp;quot;:http://doc.qt.nokia.com/latest/qtextedit.html, czyli dwóch klas, których użyjemy w tym przykładzie. Wszystkie klasy Qt posiadają pliki nagłówkowe nazwane tak samo jak nazwy klas, których dotyczą.
<br />W 6 linijce tworzony jest obiekt typu &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/latest/qapplication.html. Zarządza on zasobami aplikacji i jest niezbędny do uruchomienia jakiegokolwiek programu Qt mającego GUI. Parametry argv i args są wymagane, ponieważ każda aplikacja Qt obsługuje zestaw opcji, które można przekazać do programu z linii poleceń (np. -graphicssystem).
<br />W 8 linijce powstaje obiekt typu &quot;QTextEdit&amp;quot;:http://doc.qt.nokia.com/latest/qtextedit.html. Jest to element mający wizualną reprezentację w GUI, a takie w Qt nazywamy widżetami (z ang. ''widget''). Inne widżety to np. pasek przesuwania (ang. ''scroll bar''), etykieta (ang. ''label'') czy przycisk opcji (ang. ''radio button''). Widżet może być także kontenerem dla innych widżetów, a okno dialogowe jest tego przykładem.
<br />Linijka 9 powoduje wyświetlenie się pola edycji tekstu z jego własną ramką okna. Ponieważ widżety funkcjonują także jako kontenery (np. &quot;QMainWindow&amp;quot;:http://doc.qt.nokia.com/latest/qmainwindow.html z jego paskami narzędzi, menu, statusu i paroma innymi widżetami), możliwe jest wyświetlenie pojedynczego widżetu w jego własnym oknie. Widżety nie są domyślnie widoczne, ale funkcja &quot;show()&quot;:http://doc.qt.nokia.com/latest/qwidget.html#show pozwala nam zmienić ten stan rzeczy.
<br />Ostatnia linijka w funkcji main() odpowiedzialna jest za wejście obiektu typu &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/latest/qapplication.html w jego pętlę zdarzeń (ang. ''event loop''). Programy oparte na Qt korzystają ze zdarzeń, które są generowane i przesyłane w trakcie działania aplikacji między widżetami. Takie zdarzenia to np. naciśnięcie klawisza na klawiaturze lub myszy. W trakcie pisania tekstu w polu edycji, widżet je reprezentujący odbiera zdarzenia informujące o naciśnięciu poszczególnych klawiszy i rysuje wpisany tekst.
<br />Nim uruchomimy naszą aplikację, musimy ją najpierw zbudować. Dokonać tego możemy otwierając z okno z linią poleceń, przechodząc do katalogu, w którym trzymamy wyżej zaprezentowany plik .cpp z kodem programu i wykonując następujące polecenia:<br /><code><br />qmake -project<br />qmake<br />make<br /></code>
<br />To spowoduje utworzenie pliku wykonywalnego (w systemie Windows może zaistnieć potrzeba użycia polecenia nmake zamiast make; ponadto plik będzie umieszczony w podkatalogu debug lub release). qmake to narzędzie Qt wspierające budowanie aplikacji poprzez generację plików &quot;Makefile&amp;quot;:http://pl.wikipedia.org/wiki/Make#Makefile, które opisują proces budowania, na bazie specjalnych plików konfiguracyjnych. Taki plik konfiguracyjny (o rozszerzeniu .pro) może zostać wygenerowany automatycznie również dzięki aplikacji qmake przy użyciu opcji <s>project. Pisaniem własnych plików .pro zajmiemy się później.
<br />h3. Dowiedz się więcej
<br />* Widżety i geometria okien</s> &quot;Window and Dialog Widgets&amp;quot;:http://doc.qt.nokia.com/latest/application-windows.html<br />''' Zdarzenia i ich obsługa - &quot;The Event System&amp;quot;:http://doc.qt.nokia.com/latest/eventsandfilters.html


W 8 linijce powstaje obiekt typu [http://doc.qt.nokia.com/latest/qtextedit.html QTextEdit] ''[doc.qt.nokia.com]''. Jest to element mający wizualną reprezentację w <span class="caps">GUI</span>, a takie w Qt ######## widżetami (z ang. ''widget''). Inne widżety to np. pasek przesuwania (ang. ''scroll bar''), etykieta (ang. ''label'') czy przycisk opcji (ang. ''radio button''). Widżet może być także kontenerem dla innych widżetów, a okno dialogowe jest tego przykładem.
== Dodanie przycisku Quit ==


Linijka 9 powoduje wyświetlenie się pola edycji tekstu z jego własną ramką okna. Ponieważ widżety funkcjonują także jako kontenery (np. [http://doc.qt.nokia.com/latest/qmainwindow.html QMainWindow] ''[doc.qt.nokia.com]'' z jego paskami narzędzi, menu, statusu i paroma innymi widżetami), możliwe jest wyświetlenie pojedynczego widżetu w jego własnym oknie. Widżety nie są domyślnie widoczne, ale funkcja [http://doc.qt.nokia.com/latest/qwidget.html#show show()] ''[doc.qt.nokia.com]'' pozwala nam zmienić ten stan rzeczy.
W prawdziwej aplikacji zazwyczaj potrzeba więcej niż jednego widżetu. Dodamy więc QPushButton – przycisk – pod polem edycji tekstu. Przycisk ten sprawi, że aplikacja zakończy się w momencie jego naciśnięcia (np. za pomocą kliknięcia myszą).


Ostatnia linijka w funkcji main() odpowiedzialna jest za wejście obiektu typu [http://doc.qt.nokia.com/latest/qapplication.html QApplication] ''[doc.qt.nokia.com]'' w jego pętlę zdarzeń (ang. ''event loop''). Programy oparte na Qt korzystają ze zdarzeń, które są generowane i przesyłane w trakcie działania aplikacji między widżetami. Takie zdarzenia to np. naciśnięcie klawisza na klawiaturze lub myszy. W trakcie pisania tekstu w polu edycji, widżet je reprezentujący odbiera zdarzenia informujące o naciśnięciu poszczególnych klawiszy i rysuje wpisany tekst.
[[Image:http://doc.qt.nokia.com/latest/images/gs2.png|screenshot]]


Nim uruchomimy naszą aplikację, musimy ją najpierw zbudować. Dokonać tego możemy otwierając z okno z linią poleceń, przechodząc do katalogu, w którym trzymamy wyżej zaprezentowany plik .cpp z kodem programu i wykonując następujące polecenia:<br />
Kod źródłowy dla tego przykładu:<br /><code><br />#include &lt;QtGui&amp;gt;


To spowoduje utworzenie pliku wykonywalnego (w systemie Windows może zaistnieć potrzeba użycia polecenia nmake zamiast make; ponadto plik będzie umieszczony w podkatalogu debug lub release). qmake to narzędzie Qt wspierające budowanie aplikacji poprzez generację plików [http://pl.wikipedia.org/wiki/Make#Makefile Makefile] ''[pl.wikipedia.org]'', które opisują proces budowania, na bazie specjalnych plików konfiguracyjnych. Taki plik konfiguracyjny (o rozszerzeniu .pro) może zostać wygenerowany automatycznie również dzięki aplikacji qmake przy użyciu opcji -project. Pisaniem własnych plików .pro zajmiemy się później.
int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);


===Dowiedz się więcej===
QTextEdit textEdit;<br /> QPushButton quitButton(&quot;Quit&amp;quot;);


* Widżety i geometria okien – [http://doc.qt.nokia.com/latest/application-windows.html Window and Dialog Widgets] ''[doc.qt.nokia.com]''
QObject::connect(&amp;quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
* Zdarzenia i ich obsługa – [http://doc.qt.nokia.com/latest/eventsandfilters.html The Event System] ''[doc.qt.nokia.com]''


==Dodanie przycisku Quit==
QVBoxLayout layout;<br /> layout.addWidget(&amp;textEdit);<br /> layout.addWidget(&amp;quitButton);


W prawdziwej aplikacji zazwyczaj potrzeba więcej niż jednego widżetu. Dodamy więc QPushButton – przycisk – pod polem edycji tekstu. Przycisk ten sprawi, że aplikacja zakończy się w momencie jego naciśnięcia (np. za pomocą kliknięcia myszą).
QWidget window;<br /> window.setLayout(&amp;layout);


[[Image:gs2.png|screenshot]]
window.show();


Kod źródłowy dla tego przykładu:<br />
return app.exec&amp;amp;#40;&amp;#41;;<br />}<br /></code>


W 10 linijce wykorzystujemy mechanizm sygnałów i slotów Qt, aby sprawić, że aplikacja zakończy się, kiedy przycisk '''Quit''' zostanie naciśnięty. Sygnał, kiedy uruchomiony, wywoła wszystkie powiązane z nim sloty.
W 10 linijce wykorzystujemy mechanizm sygnałów i slotów Qt, aby sprawić, że aplikacja zakończy się, kiedy przycisk '''Quit''' zostanie naciśnięty. Sygnał, kiedy uruchomiony, wywoła wszystkie powiązane z nim sloty.


[http://doc.qt.nokia.com/latest/qcoreapplication.html#quit quit()] ''[doc.qt.nokia.com]'' jest slotem klasy [http://doc.qt.nokia.com/latest/qapplication.html QApplication] ''[doc.qt.nokia.com]'', który zakańcza aplikację. [http://doc.qt.nokia.com/latest/qabstractbutton.html#clicked clicked()] ''[doc.qt.nokia.com]'' to sygnał [http://doc.qt.nokia.com/latest/qpsuhbutton.html QPushButton] ''[doc.qt.nokia.com]'', który emitowany jest, gdy przycisk zostanie przyciśnięty. Statyczna metoda [http://doc.qt.nokia.com/latest/qobject.html#connect QObject::connect()] ''[doc.qt.nokia.com]'' zajmuje się dowiązaniem slotu do sygnału. ''<span class="caps">SIGNAL</span>'' oraz ''<span class="caps">SLOT</span>'' to dwa makra, które opisują metody mające zostać ze sobą powiązane. Trzeba również podać wskaźniki do obiektów, które emitują i otrzymują dany sygnał.
&quot;quit()&quot;:http://doc.qt.nokia.com/latest/qcoreapplication.html#quit jest slotem klasy &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/latest/qapplication.html, który zakańcza aplikację. &quot;clicked()&quot;:http://doc.qt.nokia.com/latest/qabstractbutton.html#clicked to sygnał &quot;QPushButton&amp;quot;:http://doc.qt.nokia.com/latest/qpsuhbutton.html, który emitowany jest, gdy przycisk zostanie przyciśnięty. Statyczna metoda &quot;QObject::connect()&quot;:http://doc.qt.nokia.com/latest/qobject.html#connect zajmuje się dowiązaniem slotu do sygnału. ''SIGNAL ()_ oraz _SLOT()'' to dwa makra, które opisują metody mające zostać ze sobą powiązane. Trzeba również podać wskaźniki do obiektów, które emitują i otrzymują dany sygnał.


W linijce 12 tworzymy [http://doc.qt.nokia.com/latest/qvboxlaout.html QVBoxLayout] ''[doc.qt.nokia.com]''. Jak wspominaliśmy, widżety mogą zawierać inne widżety. Można ustawić lokalizację i wymiary każdego widżetu bezpośrednio ale zazwyczaj łatwiej jest użyć layoutu (z ang. „rozkład” lub „układ graficzny” sposób rozmieszczenia). Layout zarządza wymiarami wszystkich swoich podwidżetów. Na przykład QVBoxLayout ustawia wszystkie podwidżety pionowo w rzędzie.
W linijce 12 tworzymy &quot;QVBoxLayout&amp;quot;:http://doc.qt.nokia.com/latest/qvboxlaout.html. Jak wspominaliśmy, widżety mogą zawierać inne widżety. Można ustawić lokalizację i wymiary każdego widżetu bezpośrednio ale zazwyczaj łatwiej jest użyć layoutu (z ang. „rozkład” lub „układ graficzny” - sposób rozmieszczenia). Layout zarządza wymiarami wszystkich swoich podwidżetów. Na przykład QVBoxLayout ustawia wszystkie podwidżety pionowo w rzędzie.


Linijki 13 oraz 14 dodają pole edycji tekstu oraz przycisk do layoutu. W linijce 17 ustawiony zostaje layout naszego widżetu.
Linijki 13 oraz 14 dodają pole edycji tekstu oraz przycisk do layoutu. W linijce 17 ustawiony zostaje layout naszego widżetu.


===Dowiedz się więcej===
=== Dowiedz się więcej ===


* Sygnały i sloty – [http://doc.qt.nokia.com/latest/signalsandslots.html Signals &amp; Slots] ''[doc.qt.nokia.com]''
* Sygnały i sloty - &quot;Signals &amp; Slots&amp;quot;:http://doc.qt.nokia.com/latest/signalsandslots.html
* Sposoby rozmieszczania – [http://doc.qt.nokia.com/latest/layout.html Layout Management] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/latest/widgets-and-layouts.html Widgets and Layouts] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/latest/examples-layouts.html Layout Examples] ''[doc.qt.nokia.com]''
* Sposoby rozmieszczania - &quot;Layout Management&amp;quot;:http://doc.qt.nokia.com/latest/layout.html, &quot;Widgets and Layouts&amp;quot;:http://doc.qt.nokia.com/latest/widgets-and-layouts.html, &quot;Layout Examples&amp;quot;:http://doc.qt.nokia.com/latest/examples-layouts.html
* Widżety dostępne w Qt – [http://doc.qt.nokia.com/latest/gallery.html Qt Widget Gallery] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/latest/examples-widgets.html Widget Examples] ''[doc.qt.nokia.com]''
* Widżety dostępne w Qt - &quot;Qt Widget Gallery&amp;quot;:http://doc.qt.nokia.com/latest/gallery.html, &quot;Widget Examples&amp;quot;:http://doc.qt.nokia.com/latest/examples-widgets.html


==Definiowanie klas pochodnych od QWidget==
== Definiowanie klas pochodnych od QWidget ==


Kiedy użytkownik chce wyjść z aplikacji, możesz chcieć pokazać okno dialogowe, które pyta, czy on, lub ona, rzeczywiście tego chce. W tym przykładzie, stworzymy klasę dziedziczącą z [http://doc.qt.nokia.com/latest/qwidget.html QWidget] ''[doc.qt.nokia.com]'' i dodamy slot, do którego podłączymy przycisk ''Quit''.
Kiedy użytkownik chce wyjść z aplikacji, możesz chcieć pokazać okno dialogowe, które pyta, czy on, lub ona, rzeczywiście tego chce. W tym przykładzie, stworzymy klasę dziedziczącą z &quot;QWidget&amp;quot;:http://doc.qt.nokia.com/latest/qwidget.html i dodamy slot, do którego podłączymy przycisk ''Quit''.


[[Image:gs3.png|screenshot]]
[[Image:http://doc.qt.nokia.com/latest/images/gs3.png|screenshot]]


Spójrzmy na kod źródłówy:<br />
Spójrzmy na kod źródłówy:<br /><code><br />#include &lt;QtGui&amp;gt;


Makro ''Q_OBJECT'' musi być pierwszym elementem w definicji klasy. Deklaruje ono naszą klasę jako [http://doc.qt.nokia.com/latest/qobject.html QObject] ''[doc.qt.nokia.com]'' (oczywiście musi ona również dziedziczyć z [http://doc.qt.nokia.com/latest/qobject.html QObject] ''[doc.qt.nokia.com]''). Dodaje to kilka funkcjonalności do zwykłej klasy C++. Przede wszystkim, ##### klasy i jej slotów mogą być pobrane w trakcie działania programu. Można również pobrać typy parametrów tych slotów i je wywołać.
class Notepad : public QWidget<br />{<br /> Q_OBJECT<br /> QPushButton quitButton(&quot;Quit&amp;quot;);<br />public:<br /> Notepad();


W linijce 13 deklarowany jest, przy użyciu makra ''slots'', slot quit(). Teraz można podłączyć ten slot do sygnałów ze zgadzającą się sygnaturą, tj. z jakimkolwiek sygnałem, który nie ma parametrów.
private slots:<br /> void quit();<br /> layout.addWidget(&amp;quitButton);<br />private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br />};<br /></code>


Zamiast ustawiania <span class="caps">GUI</span> i łączenia slotów w funkcji main(), użyjemy konstruktora klasy Notepad.
Makro ''Q_OBJECT'' musi być pierwszym elementem w definicji klasy. Deklaruje ono naszą klasę jako &quot;QObject&amp;quot;:http://doc.qt.nokia.com/latest/qobject.html (oczywiście musi ona również dziedziczyć z &quot;QObject&amp;quot;:http://doc.qt.nokia.com/latest/qobject.html). Dodaje to kilka funkcjonalności do zwykłej klasy C++. Przede wszystkim, nazwa klasy i jej slotów mogą być pobrane w trakcie działania programu. Można również pobrać typy parametrów tych slotów i je wywołać.


Jak widać było w definicji klasy, używamy wskaźników do naszych QObject-ów (textEdit oraz quitButton). Z zasady zawsze powinno się tworzyć [http://doc.qt.nokia.com/latest/qobject.html QObiekty] ''[doc.qt.nokia.com]'' na stosie i nigdy ich nie kopiować.
W linijce 13 deklarowany jest, przy użyciu makra ''slots'', slot quit(). Teraz można podłączyć ten slot do sygnałów ze zgadzającą się sygnaturą, tj. z jakimkolwiek sygnałem, który nie ma parametrów.
 
Następnie używamy metody [http://doc.qt.nokia.com/latest/qobject.html#tr tr()] ''[doc.qt.nokia.com]'' dla wszystkich widocznych dla użytkownika ciągów tekstu. Metoda ta jest niezbędna jeżeli chcesz udostępniać swoją aplikację w więcej niż jednym języku (np. po polsku i po angielsku). Nie będziemy wchodzić w szczegóły, możesz zgłębić temat pod linkiem Qt Linguist Manual z tabeli poniżej.
 
===Dowiedz się więcej===
 
* tr() i internacjonalizacja – [http://doc.qt.nokia.com/latest/linguist-manual.html Qt Linguist Manual] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/latest/i18n-source-translation.html Writing Source Code for Translation] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/latest/linguist-hellotr.html Hello tr() Example] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/latest/internationalization.html Internationalization with Qt] ''[doc.qt.nokia.com]''
* [http://doc.qt.nokia.com/latest/qtwebkit-bridge.html#qobjects QObiekty] ''[doc.qt.nokia.com]'' i model obiektów Qt (materiał kluczowy do zrozumienia Qt) – [http://doc.qt.nokia.com/latest/object.html Object Model] ''[doc.qt.nokia.com]''
* qmake i system budowania Qt – [http://doc.qt.nokia.com/latest/qmake-manual.html qmake Manual] ''[doc.qt.nokia.com]''
 
===Tworzenie pliku .pro===
 
Na potrzeby tego przykładu, napiszemy własny plik .pro zamiast używać qmake z opcją -project.<br />
 
Do zbudowania naszej aplikacji wystarczą teraz dwa polecenia:<br />


==Używanie QMainWindow==
Zamiast ustawiania GUI i łączenia slotów w funkcji main(), użyjemy konstruktora klasy Notepad.


Wiele aplikacji skorzysta z plusów używania [http://doc.qt.nokia.com/latest/qmainwindow.html QMainWindow] ''[doc.qt.nokia.com]''. Klasa ta dostarcza swój własny layout, do którego można dodać menu, zadokowane widgety, paski narzędzi i pasek statusu. [http://doc.qt.nokia.com/latest/qobject.html QMainWindow] ''[doc.qt.nokia.com]'' ma centralną strefę, która może być zajmowana przez dowolny widget. W naszym przypadku będzie to pole edycji tekstu.
<code><br /> Notepad::Notepad()<br /> {<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr(&quot;Quit&amp;quot;));


[[Image:gs4.png|screenshot]]
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));


Oto kod nowa definicja klasy Notepad:<br />
QVBoxLayout '''layout = new QVBoxLayout;<br /> layout-&gt;addWidget(textEdit);<br /> layout-&gt;addWidget(quitButton);
<br /> setLayout(layout);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br /> }<br /></code>
<br />Jak widać było w definicji klasy, używamy wskaźników do naszych QObject-ów (textEdit oraz quitButton). Z zasady zawsze powinno się tworzyć &quot;QObiekty&amp;quot;:http://doc.qt.nokia.com/latest/qobject.html na stosie i nigdy ich nie kopiować.
<br />Następnie używamy metody &quot;tr()&quot;:http://doc.qt.nokia.com/latest/qobject.html#tr dla wszystkich widocznych dla użytkownika ciągów tekstu. Metoda ta jest niezbędna jeżeli chcesz udostępniać swoją aplikację w więcej niż jednym języku (np. po polsku i po angielsku). Nie będziemy wchodzić w szczegóły, możesz zgłębić temat pod linkiem Qt Linguist Manual z tabeli poniżej.
<br />h3. Dowiedz się więcej
<br />''' tr() i internacjonalizacja - &quot;Qt Linguist Manual&amp;quot;:http://doc.qt.nokia.com/latest/linguist-manual.html, &quot;Writing Source Code for Translation&amp;quot;:http://doc.qt.nokia.com/latest/i18n-source-translation.html, &quot;Hello tr() Example&amp;quot;:http://doc.qt.nokia.com/latest/linguist-hellotr.html, &quot;Internationalization with Qt&amp;quot;:http://doc.qt.nokia.com/latest/internationalization.html<br />* &quot;QObiekty&amp;quot;:http://doc.qt.nokia.com/latest/qtwebkit-bridge.html#qobjects i model obiektów Qt (materiał kluczowy do zrozumienia Qt) - &quot;Object Model&amp;quot;:http://doc.qt.nokia.com/latest/object.html<br />* qmake i system budowania Qt - &quot;qmake Manual&amp;quot;:http://doc.qt.nokia.com/latest/qmake-manual.html


Dołączyliśmy dwa nowe sloty, które zapiszą i wczytają dokument. Zaimplementujemy je w następnej sekcji.
=== Tworzenie pliku .pro ===


Bardzo często w głównym oknie ten sam slot może być wywołany przez kilka widżetów. Przykładem może być opcja w menu i przycisk na pasku narzędzi. Zeby to uprościć, Qt dostarcza klasę [http://doc.qt.nokia.com/latest/qaction.html QAction] ''[doc.qt.nokia.com]'', obiektowi której podać można kilka widżetów i podłączyć go do slotu. Na przykład [http://doc.qt.nokia.com/latest/qmenu.html QMenu] ''[doc.qt.nokia.com]'' i [http://doc.qt.nokia.com/latest/qtoolbar.html QToolBar] ''[doc.qt.nokia.com]'' mogą stworzyć wpisy w menu i przycisku na pasku z tej samej QAction. Za chwilę zobaczymy, w jaki sposób to zrobić.
Na potrzeby tego przykładu, napiszemy własny plik .pro zamiast używać qmake z opcją <s>project.<br /><code><br />HEADERS = notepad.h<br />SOURCES = notepad.cpp  main.cpp<br /></code>
<br />Do zbudowania naszej aplikacji wystarczą teraz dwa polecenia:<br /><code><br />qmake<br />make<br /></code>
<br />h2. Używanie QMainWindow
<br />Wiele aplikacji skorzysta z plusów używania &quot;QMainWindow&amp;quot;:http://doc.qt.nokia.com/latest/qmainwindow.html. Klasa ta dostarcza swój własny layout, do którego można dodać menu, zadokowane widgety, paski narzędzi i pasek statusu. &quot;QMainWindow&amp;quot;:http://doc.qt.nokia.com/latest/qobject.html ma centralną strefę, która może być zajmowana przez dowolny widget. W naszym przypadku będzie to pole edycji tekstu.
<br />[[Image:http://doc.qt.nokia.com/latest/images/gs4.png|screenshot]]
<br />Oto kod nowa definicja klasy Notepad:<br /><code><br /> #include &lt;QtGui&amp;gt;
<br /> class Notepad : public QMainWindow<br /> {<br /> Q_OBJECT
<br /> public:<br /> Notepad();
<br /> private slots:<br /> void open();<br /> void save();<br /> void quit();
<br /> private:<br /> QTextEdit *textEdit;
<br /> QAction *openAction;<br /> QAction *saveAction;<br /> QAction *exitAction;
<br /> QMenu '''fileMenu;<br /> };<br /></code>
<br />Dołączyliśmy dwa nowe sloty, które zapiszą i wczytają dokument. Zaimplementujemy je w następnej sekcji.
<br />Bardzo często w głównym oknie ten sam slot może być wywołany przez kilka widżetów. Przykładem może być opcja w menu i przycisk na pasku narzędzi. Zeby to uprościć, Qt dostarcza klasę &quot;QAction&amp;quot;:http://doc.qt.nokia.com/latest/qaction.html, obiektowi której podać można kilka widżetów i podłączyć go do slotu. Na przykład &quot;QMenu&amp;quot;:http://doc.qt.nokia.com/latest/qmenu.html i &quot;QToolBar&amp;quot;:http://doc.qt.nokia.com/latest/qtoolbar.html mogą stworzyć wpisy w menu i przycisku na pasku z tej samej QAction. Za chwilę zobaczymy, w jaki sposób to zrobić.
<br />Tak jak wcześniej, używamy konstruktora klasy Notepad do zestawienia GUI:
<br /><code><br /> Notepad::Notepad()<br /> {<br /> saveAction = new QAction(tr(&quot;&amp;Open&amp;quot;), this);<br /> saveAction = new QAction(tr(&quot;&amp;Save&amp;quot;), this);<br /> exitAction = new QAction(tr(&quot;E&amp;amp;xit&amp;quot;), this);
<br /> connect(openAction, SIGNAL (triggered()), this, SLOT (open()));<br /> connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));<br /> connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
<br /> fileMenu = menuBar()<s>&gt;addMenu(tr(&quot;&amp;File&amp;quot;));<br /> fileMenu</s>&gt;addAction(openAction);<br /> fileMenu-&gt;addAction(saveAction);<br /> fileMenu-&gt;addSeparator();<br /> fileMenu-&gt;addAction(exitAction);
<br /> textEdit = new QTextEdit;<br /> setCentralWidget(textEdit);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br /> }<br /></code>
<br />&quot;QAction&amp;quot;:http://doc.qt.nokia.com/latest/qaction.html tworzone są z tekstu, który ma pojawić się na widżecie, do którego je dodajemy - w tym przypadku do opcji w menu. Gdybyśmy chcieli dodać akcje dodatkowo do paska narzędzi, moglibyśmy dać im również &quot;ikony&amp;quot;:http://doc.qt.nokia.com/latest/qicon.html.
<br />Teraz, w momencie kliknięcia wpisu w menu, uruchomi on akcję i wywoła odpowiedni slot.
<br />h3. Dowiedz się więcej
<br />''' Główne okna i klasy je udostępniające</s> &quot;Application Main Window&amp;quot;:http://doc.qt.nokia.com/latest/mainwindow.html, &quot;Main Window Examples&amp;quot;:http://doc.qt.nokia.com/latest/examples-mainwindow.html<br />* Aplikacje MDI - &quot;QMdiArea&amp;quot;:http://doc.qt.nokia.com/latest/qmdiarea.html, &quot;MDI Example&amp;quot;:http://doc.qt.nokia.com/latest/mainwindows-mdi.html


Tak jak wcześniej, używamy konstruktora klasy Notepad do zestawienia <span class="caps">GUI</span>:
== Zapisywanie i ładowanie ==
 
[http://doc.qt.nokia.com/latest/qaction.html QAction] ''[doc.qt.nokia.com]'' tworzone są z tekstu, który ma pojawić się na widżecie, do którego je dodajemy – w tym przypadku do opcji w menu. Gdybyśmy chcieli dodać akcje dodatkowo do paska narzędzi, moglibyśmy dać im również [http://doc.qt.nokia.com/latest/qicon.html ikony] ''[doc.qt.nokia.com]''.
 
Teraz, w momencie kliknięcia wpisu w menu, uruchomi on akcję i wywoła odpowiedni slot.
 
===Dowiedz się więcej===
 
* Główne okna i klasy je udostępniające – [http://doc.qt.nokia.com/latest/mainwindow.html Application Main Window] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/latest/examples-mainwindow.html Main Window Examples] ''[doc.qt.nokia.com]''
* Aplikacje <span class="caps">MDI</span> – [http://doc.qt.nokia.com/latest/qmdiarea.html QMdiArea] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/latest/mainwindows-mdi.html <span class="caps">MDI</span> Example] ''[doc.qt.nokia.com]''
 
==Zapisywanie i ładowanie==


W tym przykładzie, zaimplementujemy funkcjonalność slotów ''open()'' oraz ''save()'', które dodaliśmy w poprzedniej sekcji.
W tym przykładzie, zaimplementujemy funkcjonalność slotów ''open()'' oraz ''save()'', które dodaliśmy w poprzedniej sekcji.


[[Image:gs4.png|screenshot]]
[[Image:http://doc.qt.nokia.com/latest/images/gs4.png|screenshot]]


Zaczniemy od slotu ''open()'':
Zaczniemy od slotu ''open()'':


Pierwszy krok to zapytanie użytkownika o nazwę pliku do wczytania. Qt dostarcza [http://doc.qt.nokia.com/latest/qfiledialog.html QFileDialog] ''[doc.qt.nokia.com]'', który jest oknem dialogowym, gdzie użytkownik wybiera plik. Obrazek wyżej ukazuje takie okno na systemie Kubuntu. Statyczna metoda [http://doc.qt.nokia.com/latest/qfiledialog.html#getOpenFileName getOpenFileName()] ''[doc.qt.nokia.com]'' wyświetla modalne okno dialogowe i nie zwraca wartości dopóki użytkownik nie wybierze pliku. Zwracana przez nią wartość to ścieżka do wybranego pliku, lub pusty ciąg jeżeli użytkownik anulowal wybór.
<code><br /> QString fileName = QFileDialog::getOpenFileName(this, tr(&quot;Open File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp *.h)&quot;));
 
Gdy mamy ścieżkę, otwieramy plik metodą [http://doc.qt.nokia.com/latest/qiodevice.html#open open()] ''[doc.qt.nokia.com]'', która zwraca ''true'', jeżeli operacja się powiodła. Nie będziemy zgłębiać obsługi błędów, jest ona opisane w linkach z tabeli '''Dowiedz się więcej'''. Jeżeli otwarcie pliku jest niemożliwe, używamy [http://doc.qt.nokia.com/latest/qmessagebox.html QMessageBox] ''[doc.qt.nokia.com]'' do wyświetlenia okna z komunikatem błędu (zobacz opis klasy [http://doc.qt.nokia.com/latest/qmessagebox.html QMessageBox] ''[doc.qt.nokia.com]'' po więcej szczegółów).


Sam odczyt danych jest trywialny dzięki użyciu metody [http://doc.qt.nokia.com/latest/qiodevice.html#readAll readAll()] ''[doc.qt.nokia.com]'', która zwraca wszystkie dane w postaci [http://doc.qt.nokia.com/latest/qbytearray.html QByteArray] ''[doc.qt.nokia.com]''. [http://doc.qt.nokia.com/latest/qbytearray.html#constData constData()] ''[doc.qt.nokia.com]'' zwraca tablicę jako const char*, dla której klasa [http://doc.qt.nokia.com/latest/qstring.html QString] ''[doc.qt.nokia.com]'' ma zdefiniowany konstruktor. Następnie zawartość pliku może być wyświetlona w polu edycji. Możemy więc zamknąć plik metodą [http://doc.qt.nokia.com/latest/qiodevice.html#close close()] ''[doc.qt.nokia.com]'', aby oddać systemowi operacyjnemu deskryptor pliku.
if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::ReadOnly)) {<br /> QMessageBox::critical(this, tr(&quot;Error&amp;quot;),<br /> tr(&quot;Could not open file&amp;quot;));<br /> return;<br /> }<br /> QString contents = file.readAll().constData();<br /> textEdit-&gt;setPlainText(contents);<br /> file.close();<br /> }<br /></code>


Przejdźmy do slotu ''save()'':
Pierwszy krok to zapytanie użytkownika o nazwę pliku do wczytania. Qt dostarcza &quot;QFileDialog&amp;quot;:http://doc.qt.nokia.com/latest/qfiledialog.html, który jest oknem dialogowym, gdzie użytkownik wybiera plik. Obrazek wyżej ukazuje takie okno na systemie Kubuntu. Statyczna metoda &quot;getOpenFileName()&quot;:http://doc.qt.nokia.com/latest/qfiledialog.html#getOpenFileName wyświetla modalne okno dialogowe i nie zwraca wartości dopóki użytkownik nie wybierze pliku. Zwracana przez nią wartość to ścieżka do wybranego pliku, lub pusty ciąg jeżeli użytkownik anulowal wybór.


Do zapisywania zawartości pola edycji do pliku używamy klasy [http://doc.qt.nokia.com/latest/qtextstream.html QTextStream] ''[doc.qt.nokia.com]'', która opakowuje obiekt [http://doc.qt.nokia.com/latest/qfile.html QFile] ''[doc.qt.nokia.com]''. Strumień może zapisywać [http://doc.qt.nokia.com/latest/qstring.html QString] ''[doc.qt.nokia.com]'' bezpośrednio do pliku, natomiast [http://doc.qt.nokia.com/latest/qfile.html QFile] ''[doc.qt.nokia.com]'' akceptuje jedynie czyste dane (''char*'') przy pomocy metody [http://doc.qt.nokia.com/latest/qiodevice.html#write write()] ''[doc.qt.nokia.com]'' z klasy [http://doc.qt.nokia.com/latest/qiodevice.html <span class="caps">QIOD</span>evice] ''[doc.qt.nokia.com]''.
Gdy mamy ścieżkę, otwieramy plik metodą &quot;open()&quot;:http://doc.qt.nokia.com/latest/qiodevice.html#open, która zwraca ''true'', jeżeli operacja się powiodła. Nie będziemy zgłębiać obsługi błędów, jest ona opisane w linkach z tabeli '''Dowiedz się więcej'''. Jeżeli otwarcie pliku jest niemożliwe, używamy &quot;QMessageBox&amp;quot;:http://doc.qt.nokia.com/latest/qmessagebox.html do wyświetlenia okna z komunikatem błędu (zobacz opis klasy &quot;QMessageBox&amp;quot;:http://doc.qt.nokia.com/latest/qmessagebox.html po więcej szczegółów).


===Dowiedz się więcej===
Sam odczyt danych jest trywialny dzięki użyciu metody &quot;readAll()&quot;:http://doc.qt.nokia.com/latest/qiodevice.html#readAll, która zwraca wszystkie dane w postaci &quot;QByteArray&amp;quot;:http://doc.qt.nokia.com/latest/qbytearray.html. &quot;constData()&quot;:http://doc.qt.nokia.com/latest/qbytearray.html#constData zwraca tablicę jako const char*, dla której klasa &quot;QString&amp;quot;:http://doc.qt.nokia.com/latest/qstring.html ma zdefiniowany konstruktor. Następnie zawartość pliku może być wyświetlona w polu edycji. Możemy więc zamknąć plik metodą &quot;close()&quot;:http://doc.qt.nokia.com/latest/qiodevice.html#close, aby oddać systemowi operacyjnemu deskryptor pliku.


* Pliki i urządzenia we/wy – [http://doc.qt.nokia.com/latest/qfile.html QFile] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/latest/qiodevice.html <span class="caps">QIOD</span>evice] ''[doc.qt.nokia.com]''
Przejdźmy do slotu ''save()'':


''It’s free translation of the [http://doc.qt.nokia.com/latest/gettingstartedqt.html Getting Started Programming with Qt] ''[doc.qt.nokia.com]'' article.''
<code><br /> QString fileName = QFileDialog::getSaveFileName(this, tr(&quot;Save File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp '''.h)&quot;));
<br /> if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::WriteOnly)) {<br /> // error message<br /> } else {<br /> QTextStream stream(&amp;file);<br /> stream &lt;&lt; textEdit-&gt;toPlainText();<br /> stream.flush();<br /> file.close();<br /> }<br /> }<br /></code>
<br />Do zapisywania zawartości pola edycji do pliku używamy klasy &quot;QTextStream&amp;quot;:http://doc.qt.nokia.com/latest/qtextstream.html, która opakowuje obiekt &quot;QFile&amp;quot;:http://doc.qt.nokia.com/latest/qfile.html. Strumień może zapisywać &quot;QString&amp;quot;:http://doc.qt.nokia.com/latest/qstring.html bezpośrednio do pliku, natomiast &quot;QFile&amp;quot;:http://doc.qt.nokia.com/latest/qfile.html akceptuje jedynie czyste dane (''char*'') przy pomocy metody &quot;write()&quot;:http://doc.qt.nokia.com/latest/qiodevice.html#write z klasy &quot;QIODevice&amp;quot;:http://doc.qt.nokia.com/latest/qiodevice.html.
<br />h3. Dowiedz się więcej
<br />''' Pliki i urządzenia we/wy - &quot;QFile&amp;quot;:http://doc.qt.nokia.com/latest/qfile.html, &quot;QIODevice&amp;quot;:http://doc.qt.nokia.com/latest/qiodevice.html

Revision as of 14:31, 23 February 2015

h1. Pierwsze kroki w programowaniu z Qt

Witamy w świecie Qt - wieloplatformowego zestawu narzędzi i bibliotek do tworzenia aplikacji z graficznym interfejsem użytkownika (GUI) i nie tylko. Nauczymy cię tutaj podstaw Qt pokazując jak zaimplementować prostą aplikację typu Notatnik. Po lekturze tego przewodnika powinieneś być gotów do zagłębienia się w dokumentację API oraz omówień poszczególnych modułów i rozwiązań dostępnych w Qt. Znajdywanie informacji potrzebnych do stworzenia aplikacji, którą zapewne od dawna planujesz napisać, będzie wówczas przebiegać sprawniej.

Powitalny notatnik

W pierwszym przykładzie stworzymy i pokażemy pole edycji tekstu w jego własnym oknie. Jest to najprostszy możliwy program napisany w Qt posiadający GUI.

screenshot

Tak wygląda kod owej aplikacji:

<br />#include &lt;QApplication&amp;gt;<br />#include &lt;QTextEdit&amp;gt;

int main(int argv, char *'''args)<br />{<br /> QApplication app(argv, args);
<br /> QTextEdit textEdit;<br /> textEdit.show();
<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}<br />


Prześledźmy go linijka po linijce. W dwóch pierwszych dołączamy pliki nagłówkowe "QApplication&quot;:http://doc.qt.nokia.com/latest/qapplication.html i "QTextEdit&quot;:http://doc.qt.nokia.com/latest/qtextedit.html, czyli dwóch klas, których użyjemy w tym przykładzie. Wszystkie klasy Qt posiadają pliki nagłówkowe nazwane tak samo jak nazwy klas, których dotyczą.
W 6 linijce tworzony jest obiekt typu "QApplication&quot;:http://doc.qt.nokia.com/latest/qapplication.html. Zarządza on zasobami aplikacji i jest niezbędny do uruchomienia jakiegokolwiek programu Qt mającego GUI. Parametry argv i args są wymagane, ponieważ każda aplikacja Qt obsługuje zestaw opcji, które można przekazać do programu z linii poleceń (np. -graphicssystem).
W 8 linijce powstaje obiekt typu "QTextEdit&quot;:http://doc.qt.nokia.com/latest/qtextedit.html. Jest to element mający wizualną reprezentację w GUI, a takie w Qt nazywamy widżetami (z ang. widget). Inne widżety to np. pasek przesuwania (ang. scroll bar), etykieta (ang. label) czy przycisk opcji (ang. radio button). Widżet może być także kontenerem dla innych widżetów, a okno dialogowe jest tego przykładem.
Linijka 9 powoduje wyświetlenie się pola edycji tekstu z jego własną ramką okna. Ponieważ widżety funkcjonują także jako kontenery (np. "QMainWindow&quot;:http://doc.qt.nokia.com/latest/qmainwindow.html z jego paskami narzędzi, menu, statusu i paroma innymi widżetami), możliwe jest wyświetlenie pojedynczego widżetu w jego własnym oknie. Widżety nie są domyślnie widoczne, ale funkcja "show()":http://doc.qt.nokia.com/latest/qwidget.html#show pozwala nam zmienić ten stan rzeczy.
Ostatnia linijka w funkcji main() odpowiedzialna jest za wejście obiektu typu "QApplication&quot;:http://doc.qt.nokia.com/latest/qapplication.html w jego pętlę zdarzeń (ang. event loop). Programy oparte na Qt korzystają ze zdarzeń, które są generowane i przesyłane w trakcie działania aplikacji między widżetami. Takie zdarzenia to np. naciśnięcie klawisza na klawiaturze lub myszy. W trakcie pisania tekstu w polu edycji, widżet je reprezentujący odbiera zdarzenia informujące o naciśnięciu poszczególnych klawiszy i rysuje wpisany tekst.


Nim uruchomimy naszą aplikację, musimy ją najpierw zbudować. Dokonać tego możemy otwierając z okno z linią poleceń, przechodząc do katalogu, w którym trzymamy wyżej zaprezentowany plik .cpp z kodem programu i wykonując następujące polecenia:

<br />qmake -project<br />qmake<br />make<br />


To spowoduje utworzenie pliku wykonywalnego (w systemie Windows może zaistnieć potrzeba użycia polecenia nmake zamiast make; ponadto plik będzie umieszczony w podkatalogu debug lub release). qmake to narzędzie Qt wspierające budowanie aplikacji poprzez generację plików "Makefile&quot;:http://pl.wikipedia.org/wiki/Make#Makefile, które opisują proces budowania, na bazie specjalnych plików konfiguracyjnych. Taki plik konfiguracyjny (o rozszerzeniu .pro) może zostać wygenerowany automatycznie również dzięki aplikacji qmake przy użyciu opcji project. Pisaniem własnych plików .pro zajmiemy się później.
h3. Dowiedz się więcej
* Widżety i geometria okien
"Window and Dialog Widgets&quot;:http://doc.qt.nokia.com/latest/application-windows.html
Zdarzenia i ich obsługa - "The Event System&quot;:http://doc.qt.nokia.com/latest/eventsandfilters.html

Dodanie przycisku Quit

W prawdziwej aplikacji zazwyczaj potrzeba więcej niż jednego widżetu. Dodamy więc QPushButton – przycisk – pod polem edycji tekstu. Przycisk ten sprawi, że aplikacja zakończy się w momencie jego naciśnięcia (np. za pomocą kliknięcia myszą).

screenshot

Kod źródłowy dla tego przykładu:

<br />#include &lt;QtGui&amp;gt;

int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);

QTextEdit textEdit;<br /> QPushButton quitButton(&quot;Quit&amp;quot;);

QObject::connect(&amp;quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));

QVBoxLayout layout;<br /> layout.addWidget(&amp;textEdit);<br /> layout.addWidget(&amp;quitButton);

QWidget window;<br /> window.setLayout(&amp;layout);

window.show();

return app.exec&amp;amp;#40;&amp;#41;;<br />}<br />

W 10 linijce wykorzystujemy mechanizm sygnałów i slotów Qt, aby sprawić, że aplikacja zakończy się, kiedy przycisk Quit zostanie naciśnięty. Sygnał, kiedy uruchomiony, wywoła wszystkie powiązane z nim sloty.

"quit()":http://doc.qt.nokia.com/latest/qcoreapplication.html#quit jest slotem klasy "QApplication&quot;:http://doc.qt.nokia.com/latest/qapplication.html, który zakańcza aplikację. "clicked()":http://doc.qt.nokia.com/latest/qabstractbutton.html#clicked to sygnał "QPushButton&quot;:http://doc.qt.nokia.com/latest/qpsuhbutton.html, który emitowany jest, gdy przycisk zostanie przyciśnięty. Statyczna metoda "QObject::connect()":http://doc.qt.nokia.com/latest/qobject.html#connect zajmuje się dowiązaniem slotu do sygnału. SIGNAL ()_ oraz _SLOT() to dwa makra, które opisują metody mające zostać ze sobą powiązane. Trzeba również podać wskaźniki do obiektów, które emitują i otrzymują dany sygnał.

W linijce 12 tworzymy "QVBoxLayout&quot;:http://doc.qt.nokia.com/latest/qvboxlaout.html. Jak wspominaliśmy, widżety mogą zawierać inne widżety. Można ustawić lokalizację i wymiary każdego widżetu bezpośrednio ale zazwyczaj łatwiej jest użyć layoutu (z ang. „rozkład” lub „układ graficzny” - sposób rozmieszczenia). Layout zarządza wymiarami wszystkich swoich podwidżetów. Na przykład QVBoxLayout ustawia wszystkie podwidżety pionowo w rzędzie.

Linijki 13 oraz 14 dodają pole edycji tekstu oraz przycisk do layoutu. W linijce 17 ustawiony zostaje layout naszego widżetu.

Dowiedz się więcej

Definiowanie klas pochodnych od QWidget

Kiedy użytkownik chce wyjść z aplikacji, możesz chcieć pokazać okno dialogowe, które pyta, czy on, lub ona, rzeczywiście tego chce. W tym przykładzie, stworzymy klasę dziedziczącą z "QWidget&quot;:http://doc.qt.nokia.com/latest/qwidget.html i dodamy slot, do którego podłączymy przycisk Quit.

screenshot

Spójrzmy na kod źródłówy:

<br />#include &lt;QtGui&amp;gt;

class Notepad : public QWidget<br />{<br /> Q_OBJECT<br /> QPushButton quitButton(&quot;Quit&amp;quot;);<br />public:<br /> Notepad();

private slots:<br /> void quit();<br /> layout.addWidget(&amp;quitButton);<br />private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br />};<br />

Makro Q_OBJECT musi być pierwszym elementem w definicji klasy. Deklaruje ono naszą klasę jako "QObject&quot;:http://doc.qt.nokia.com/latest/qobject.html (oczywiście musi ona również dziedziczyć z "QObject&quot;:http://doc.qt.nokia.com/latest/qobject.html). Dodaje to kilka funkcjonalności do zwykłej klasy C++. Przede wszystkim, nazwa klasy i jej slotów mogą być pobrane w trakcie działania programu. Można również pobrać typy parametrów tych slotów i je wywołać.

W linijce 13 deklarowany jest, przy użyciu makra slots, slot quit(). Teraz można podłączyć ten slot do sygnałów ze zgadzającą się sygnaturą, tj. z jakimkolwiek sygnałem, który nie ma parametrów.

Zamiast ustawiania GUI i łączenia slotów w funkcji main(), użyjemy konstruktora klasy Notepad.

<br /> Notepad::Notepad()<br /> {<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr(&quot;Quit&amp;quot;));

connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));

QVBoxLayout '''layout = new QVBoxLayout;<br /> layout-&gt;addWidget(textEdit);<br /> layout-&gt;addWidget(quitButton);
<br /> setLayout(layout);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br /> }<br />


Jak widać było w definicji klasy, używamy wskaźników do naszych QObject-ów (textEdit oraz quitButton). Z zasady zawsze powinno się tworzyć "QObiekty&quot;:http://doc.qt.nokia.com/latest/qobject.html na stosie i nigdy ich nie kopiować.
Następnie używamy metody "tr()":http://doc.qt.nokia.com/latest/qobject.html#tr dla wszystkich widocznych dla użytkownika ciągów tekstu. Metoda ta jest niezbędna jeżeli chcesz udostępniać swoją aplikację w więcej niż jednym języku (np. po polsku i po angielsku). Nie będziemy wchodzić w szczegóły, możesz zgłębić temat pod linkiem Qt Linguist Manual z tabeli poniżej.
h3. Dowiedz się więcej
tr() i internacjonalizacja - "Qt Linguist Manual&quot;:http://doc.qt.nokia.com/latest/linguist-manual.html, "Writing Source Code for Translation&quot;:http://doc.qt.nokia.com/latest/i18n-source-translation.html, "Hello tr() Example&quot;:http://doc.qt.nokia.com/latest/linguist-hellotr.html, "Internationalization with Qt&quot;:http://doc.qt.nokia.com/latest/internationalization.html
* "QObiekty&quot;:http://doc.qt.nokia.com/latest/qtwebkit-bridge.html#qobjects i model obiektów Qt (materiał kluczowy do zrozumienia Qt) - "Object Model&quot;:http://doc.qt.nokia.com/latest/object.html
* qmake i system budowania Qt - "qmake Manual&quot;:http://doc.qt.nokia.com/latest/qmake-manual.html

Tworzenie pliku .pro

Na potrzeby tego przykładu, napiszemy własny plik .pro zamiast używać qmake z opcją project.

<br />HEADERS = notepad.h<br />SOURCES = notepad.cpp  main.cpp<br />


Do zbudowania naszej aplikacji wystarczą teraz dwa polecenia:

<br />qmake<br />make<br />


h2. Używanie QMainWindow
Wiele aplikacji skorzysta z plusów używania "QMainWindow&quot;:http://doc.qt.nokia.com/latest/qmainwindow.html. Klasa ta dostarcza swój własny layout, do którego można dodać menu, zadokowane widgety, paski narzędzi i pasek statusu. "QMainWindow&quot;:http://doc.qt.nokia.com/latest/qobject.html ma centralną strefę, która może być zajmowana przez dowolny widget. W naszym przypadku będzie to pole edycji tekstu.
screenshot


Oto kod nowa definicja klasy Notepad:

<br /> #include &lt;QtGui&amp;gt;
<br /> class Notepad : public QMainWindow<br /> {<br /> Q_OBJECT
<br /> public:<br /> Notepad();
<br /> private slots:<br /> void open();<br /> void save();<br /> void quit();
<br /> private:<br /> QTextEdit *textEdit;
<br /> QAction *openAction;<br /> QAction *saveAction;<br /> QAction *exitAction;
<br /> QMenu '''fileMenu;<br /> };<br />


Dołączyliśmy dwa nowe sloty, które zapiszą i wczytają dokument. Zaimplementujemy je w następnej sekcji.
Bardzo często w głównym oknie ten sam slot może być wywołany przez kilka widżetów. Przykładem może być opcja w menu i przycisk na pasku narzędzi. Zeby to uprościć, Qt dostarcza klasę "QAction&quot;:http://doc.qt.nokia.com/latest/qaction.html, obiektowi której podać można kilka widżetów i podłączyć go do slotu. Na przykład "QMenu&quot;:http://doc.qt.nokia.com/latest/qmenu.html i "QToolBar&quot;:http://doc.qt.nokia.com/latest/qtoolbar.html mogą stworzyć wpisy w menu i przycisku na pasku z tej samej QAction. Za chwilę zobaczymy, w jaki sposób to zrobić.
Tak jak wcześniej, używamy konstruktora klasy Notepad do zestawienia GUI:


<br /> Notepad::Notepad()<br /> {<br /> saveAction = new QAction(tr(&quot;&amp;Open&amp;quot;), this);<br /> saveAction = new QAction(tr(&quot;&amp;Save&amp;quot;), this);<br /> exitAction = new QAction(tr(&quot;E&amp;amp;xit&amp;quot;), this);
<br /> connect(openAction, SIGNAL (triggered()), this, SLOT (open()));<br /> connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));<br /> connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
<br /> fileMenu = menuBar()<s>&gt;addMenu(tr(&quot;&amp;File&amp;quot;));<br /> fileMenu</s>&gt;addAction(openAction);<br /> fileMenu-&gt;addAction(saveAction);<br /> fileMenu-&gt;addSeparator();<br /> fileMenu-&gt;addAction(exitAction);
<br /> textEdit = new QTextEdit;<br /> setCentralWidget(textEdit);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br /> }<br />


"QAction&quot;:http://doc.qt.nokia.com/latest/qaction.html tworzone są z tekstu, który ma pojawić się na widżecie, do którego je dodajemy - w tym przypadku do opcji w menu. Gdybyśmy chcieli dodać akcje dodatkowo do paska narzędzi, moglibyśmy dać im również "ikony&quot;:http://doc.qt.nokia.com/latest/qicon.html.
Teraz, w momencie kliknięcia wpisu w menu, uruchomi on akcję i wywoła odpowiedni slot.
h3. Dowiedz się więcej
Główne okna i klasy je udostępniające
"Application Main Window&quot;:http://doc.qt.nokia.com/latest/mainwindow.html, "Main Window Examples&quot;:http://doc.qt.nokia.com/latest/examples-mainwindow.html
* Aplikacje MDI - "QMdiArea&quot;:http://doc.qt.nokia.com/latest/qmdiarea.html, "MDI Example&quot;:http://doc.qt.nokia.com/latest/mainwindows-mdi.html

Zapisywanie i ładowanie

W tym przykładzie, zaimplementujemy funkcjonalność slotów open() oraz save(), które dodaliśmy w poprzedniej sekcji.

screenshot

Zaczniemy od slotu open():

<br /> QString fileName = QFileDialog::getOpenFileName(this, tr(&quot;Open File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp *.h)&quot;));

if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::ReadOnly)) {<br /> QMessageBox::critical(this, tr(&quot;Error&amp;quot;),<br /> tr(&quot;Could not open file&amp;quot;));<br /> return;<br /> }<br /> QString contents = file.readAll().constData();<br /> textEdit-&gt;setPlainText(contents);<br /> file.close();<br /> }<br />

Pierwszy krok to zapytanie użytkownika o nazwę pliku do wczytania. Qt dostarcza "QFileDialog&quot;:http://doc.qt.nokia.com/latest/qfiledialog.html, który jest oknem dialogowym, gdzie użytkownik wybiera plik. Obrazek wyżej ukazuje takie okno na systemie Kubuntu. Statyczna metoda "getOpenFileName()":http://doc.qt.nokia.com/latest/qfiledialog.html#getOpenFileName wyświetla modalne okno dialogowe i nie zwraca wartości dopóki użytkownik nie wybierze pliku. Zwracana przez nią wartość to ścieżka do wybranego pliku, lub pusty ciąg jeżeli użytkownik anulowal wybór.

Gdy mamy ścieżkę, otwieramy plik metodą "open()":http://doc.qt.nokia.com/latest/qiodevice.html#open, która zwraca true, jeżeli operacja się powiodła. Nie będziemy zgłębiać obsługi błędów, jest ona opisane w linkach z tabeli Dowiedz się więcej. Jeżeli otwarcie pliku jest niemożliwe, używamy "QMessageBox&quot;:http://doc.qt.nokia.com/latest/qmessagebox.html do wyświetlenia okna z komunikatem błędu (zobacz opis klasy "QMessageBox&quot;:http://doc.qt.nokia.com/latest/qmessagebox.html po więcej szczegółów).

Sam odczyt danych jest trywialny dzięki użyciu metody "readAll()":http://doc.qt.nokia.com/latest/qiodevice.html#readAll, która zwraca wszystkie dane w postaci "QByteArray&quot;:http://doc.qt.nokia.com/latest/qbytearray.html. "constData()":http://doc.qt.nokia.com/latest/qbytearray.html#constData zwraca tablicę jako const char*, dla której klasa "QString&quot;:http://doc.qt.nokia.com/latest/qstring.html ma zdefiniowany konstruktor. Następnie zawartość pliku może być wyświetlona w polu edycji. Możemy więc zamknąć plik metodą "close()":http://doc.qt.nokia.com/latest/qiodevice.html#close, aby oddać systemowi operacyjnemu deskryptor pliku.

Przejdźmy do slotu save():

<br /> QString fileName = QFileDialog::getSaveFileName(this, tr(&quot;Save File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp '''.h)&quot;));
<br /> if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::WriteOnly)) {<br /> // error message<br /> } else {<br /> QTextStream stream(&amp;file);<br /> stream &lt;&lt; textEdit-&gt;toPlainText();<br /> stream.flush();<br /> file.close();<br /> }<br /> }<br />


Do zapisywania zawartości pola edycji do pliku używamy klasy "QTextStream&quot;:http://doc.qt.nokia.com/latest/qtextstream.html, która opakowuje obiekt "QFile&quot;:http://doc.qt.nokia.com/latest/qfile.html. Strumień może zapisywać "QString&quot;:http://doc.qt.nokia.com/latest/qstring.html bezpośrednio do pliku, natomiast "QFile&quot;:http://doc.qt.nokia.com/latest/qfile.html akceptuje jedynie czyste dane (char*) przy pomocy metody "write()":http://doc.qt.nokia.com/latest/qiodevice.html#write z klasy "QIODevice&quot;:http://doc.qt.nokia.com/latest/qiodevice.html.
h3. Dowiedz się więcej
Pliki i urządzenia we/wy - "QFile&quot;:http://doc.qt.nokia.com/latest/qfile.html, "QIODevice&quot;:http://doc.qt.nokia.com/latest/qiodevice.html