Basic Programming/cs: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
m (Wieland moved page Zaciname s Qt to Basic Programming/cs: not english)
m (Corrected link rot, replaced nokia image links with Wayback links from archive.org)
 
Line 1: Line 1:
{{Cleanup | reason=Auto-imported from ExpressionEngine.}}


= Začínáme programovat s Qt =
= Začínáme programovat s Qt =
Line 10: Line 8:
V tomto úvodním příkladu vytvoříme a zobrazíme oblast pro úpravu textu. Takto vypadá nejjednodušší možný Qt program.
V tomto úvodním příkladu vytvoříme a zobrazíme oblast pro úpravu textu. Takto vypadá nejjednodušší možný Qt program.


[[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|Ahoj Notepade]]
[[Image:https://web.archive.org/web/20140707233451if_/http://qt-project.org/doc/qt-5/images/gs1.png|Ahoj Notepade]]


A toto je jeho zdrojový kód:
A toto je jeho zdrojový kód:
Line 27: Line 25:
}</code>
}</code>


Nyní si tento zdrojový kód řádek po řádku projdeme. V prvních dvou řádcích vkládáme hlavičkové soubory pro [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] a [http://doc.qt.nokia.com/4.7/qtextedit.html QTextEdit], což jsou přávě ty třídy, které pro tento příklad potřebujeme. Názvy všech Qt hlavičkových souborů se shodují s názvy tříd které jsou v nich deklarovány.
Nyní si tento zdrojový kód řádek po řádku projdeme. V prvních dvou řádcích vkládáme hlavičkové soubory pro [https://doc.qt.io/qt-5/qapplication.html QApplication] a [https://doc.qt.io/qt-5/qtextedit.html QTextEdit], což jsou přávě ty třídy, které pro tento příklad potřebujeme. Názvy všech Qt hlavičkových souborů se shodují s názvy tříd které jsou v nich deklarovány.


Na řádku 6 vytváříme objekt třídy [http://doc.qt.nokia.com/4.7/qapplication.html QApplication]. Tento objekt spravuje prostředky celé aplikace a je vyžadován pro funkčnost všech Qt programů mající GUI. Jako parametry potřebuje argv a args, potože Qt samo od sebe přijímá několik argumentů příkazové řádky.
Na řádku 6 vytváříme objekt třídy [https://doc.qt.io/qt-5/qapplication.html QApplication]. Tento objekt spravuje prostředky celé aplikace a je vyžadován pro funkčnost všech Qt programů mající GUI. Jako parametry potřebuje argv a args, potože Qt samo od sebe přijímá několik argumentů příkazové řádky.


Řádek 8 vytváří objekt třídy [http://doc.qt.nokia.com/4.7/qtextedit.html QTextEdit]. Oblast pro úpravu textu je vizuální prvek GUI. V Qt takovéto elementy nazýváme widgety. Příklady dalších widgetů jsou například posuvníky, štítky, přepínače, atp. Widget může být zároveň kontejnerem pro další widgety; příkladem budiž hlavní okno aplikace či dialog.
Řádek 8 vytváří objekt třídy [https://doc.qt.io/qt-5/qtextedit.html QTextEdit]. Oblast pro úpravu textu je vizuální prvek GUI. V Qt takovéto elementy nazýváme widgety. Příklady dalších widgetů jsou například posuvníky, štítky, přepínače, atp. Widget může být zároveň kontejnerem pro další widgety; příkladem budiž hlavní okno aplikace či dialog.


Řádek 9 zobrazí oblast pro úpravu textu na obrazovce ve vlastním okně. Vzhledem k tomu, že widgety mohou složit i jako kontejnery (například [http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindow], který obsahuje nástrojovou lištu, menu, stavový řádek a několik dalších widgetů), je možné zobrazit widget ve vlastním okně. Widgety jsou implicitně skryty; o zobrazení se stará právě metoda [http://doc.qt.nokia.com/4.7/qwidget.html#show show()]).
Řádek 9 zobrazí oblast pro úpravu textu na obrazovce ve vlastním okně. Vzhledem k tomu, že widgety mohou složit i jako kontejnery (například [https://doc.qt.io/qt-5/qmainwindow.html QMainWindow], který obsahuje nástrojovou lištu, menu, stavový řádek a několik dalších widgetů), je možné zobrazit widget ve vlastním okně. Widgety jsou implicitně skryty; o zobrazení se stará právě metoda [https://doc.qt.io/qt-5/qwidget.html#show show()]).


Řádek 11 spustí hlavní smyčku eventů aplikace. Dokud aplikace beží, jejím widgetům jsou zasílány eventy. Příkladem eventů jsou stisknutí tlačítek myši a klávesnice. Jakmile napíšete text do dříve zmíněné oblasti pro úpravu textu, ta obdrží eventy informující o stisknutí kláves a reaguje vykreslením příslušného textu.
Řádek 11 spustí hlavní smyčku eventů aplikace. Dokud aplikace beží, jejím widgetům jsou zasílány eventy. Příkladem eventů jsou stisknutí tlačítek myši a klávesnice. Jakmile napíšete text do dříve zmíněné oblasti pro úpravu textu, ta obdrží eventy informující o stisknutí kláves a reaguje vykreslením příslušného textu.
Line 47: Line 45:
=== Rozšiřující informace ===
=== Rozšiřující informace ===
|Téma|Odkaz|
|Téma|Odkaz|
|Widgety a gemoetrie okna|[http://doc.qt.nokia.com/4.7/application-windows.html| Window and Dialog Widgets]
|Widgety a gemoetrie okna|[https://doc.qt.io/qt-5/application-windows.html| Window and Dialog Widgets]
|Eventy a jejich zpracování|[http://doc.qt.nokia.com/4.7/eventsandfilters.html| The Event System]
|Eventy a jejich zpracování|[https://doc.qt.io/qt-5/eventsandfilters.html| The Event System]


== Přídání tlačítka 'Quit' ==
== Přídání tlačítka 'Quit' ==
V reálné aplikaci budete běžně potřebovat více než jen jeden widget. Nyní přidáme [http://doc.qt.nokia.com/4.7/qpushbutton.html QPushButton] pod oblast pro úpravu textu. Toto tlačítko bude plnit funkci vypínače aplikace (společně se zavřením okna).
V reálné aplikaci budete běžně potřebovat více než jen jeden widget. Nyní přidáme [https://doc.qt.io/qt-5/qpushbutton.html QPushButton] pod oblast pro úpravu textu. Toto tlačítko bude plnit funkci vypínače aplikace (společně se zavřením okna).


[[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|Ahoj Notepade]]
[[Image:https://web.archive.org/web/20140809121237if_/http://qt-project.org/doc/qt-5/images/gs2.png|Ahoj Notepade]]


Nyní se podívejme na zdrojový kód
Nyní se podívejme na zdrojový kód
Line 80: Line 78:
}</code>
}</code>


Na řádku 1 vkládáme [http://doc.qt.nokia.com/4.7/qtgui.html QtGui], které obsahuje všechny Qt GUI třídy.
Na řádku 1 vkládáme [https://doc.qt.io/qt-5/qtgui.html QtGui], které obsahuje všechny Qt GUI třídy.


Řádek 10 používá Qt systém signálů a slotů a zajišťuje, že stisknutí tlačítka 'Quit' ukončí aplikaci. Slot je funkce, která může být vyvolána za běhu použitím jejího jména (jako doslovný řetězec). Signál je funkce, která když zavolána zavolá všechny sloty s ní propojené; tyto procedury nazýváme propojení slotu se signálem (to connect the slot to the signal) a vyslání signálu (to emit the signal).
Řádek 10 používá Qt systém signálů a slotů a zajišťuje, že stisknutí tlačítka 'Quit' ukončí aplikaci. Slot je funkce, která může být vyvolána za běhu použitím jejího jména (jako doslovný řetězec). Signál je funkce, která když zavolána zavolá všechny sloty s ní propojené; tyto procedury nazýváme propojení slotu se signálem (to connect the slot to the signal) a vyslání signálu (to emit the signal).


[http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit quit()] je slot třídy [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] , který při zavolání ukončí aplikaci. [http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked clicked()] je signál třídy, který [http://doc.qt.nokia.com/4.7/qpushbutton.html QPushButton] vyšle poté co je stisknut. Statická funkce [http://doc.qt.nokia.com/4.7/qobject.html#connect QObject::connect()] se stará o propojení signálu se slotem. SIGNAL () a SLOT() jsou dvě makra, která přebírají prototyp (type-signature) signálu a slotu k propojení.
[https://doc.qt.io/qt-5/qcoreapplication.html#quit quit()] je slot třídy [https://doc.qt.io/qt-5/qapplication.html QApplication] , který při zavolání ukončí aplikaci. [https://doc.qt.io/qt-5/qabstractbutton.html#clicked clicked()] je signál třídy, který [https://doc.qt.io/qt-5/qpushbutton.html QPushButton] vyšle poté co je stisknut. Statická funkce [https://doc.qt.io/qt-5/qobject.html#connect QObject::connect()] se stará o propojení signálu se slotem. SIGNAL () a SLOT() jsou dvě makra, která přebírají prototyp (type-signature) signálu a slotu k propojení.


Řádek 12 vytváří objekt třídy [http://doc.qt.nokia.com/4.7/qvboxlayout.html QVBoxLayout]. Jak již bylo zmíňeno, widgety mohou obsahovat další wigety. Je také možné přímo nastavit meze (umístění a velikost) potomků widgetu (widgetů, které daný widget obsahuje). Layout spravuje meze svých potomků automaticky. Například [http://doc.qt.nokia.com/4.7/qvboxlayout.html QVBoxLayout] umístí potomky vertikálně pod sebe.
Řádek 12 vytváří objekt třídy [https://doc.qt.io/qt-5/qvboxlayout.html QVBoxLayout]. Jak již bylo zmíňeno, widgety mohou obsahovat další wigety. Je také možné přímo nastavit meze (umístění a velikost) potomků widgetu (widgetů, které daný widget obsahuje). Layout spravuje meze svých potomků automaticky. Například [https://doc.qt.io/qt-5/qvboxlayout.html QVBoxLayout] umístí potomky vertikálně pod sebe.


Řádky 13 a 14 přidávájí do layoutu oblast na úpravu textu a tlačítko. Řádek 17 nastavuje nastaví widgetu hlavní layout.
Řádky 13 a 14 přidávájí do layoutu oblast na úpravu textu a tlačítko. Řádek 17 nastavuje nastaví widgetu hlavní layout.
Line 97: Line 95:
|-
|-
|Signály a Sloty
|Signály a Sloty
|[http://doc.qt.nokia.com/4.7/signalsandslots.html Signals & Slots]
|[https://doc.qt.io/qt-5/signalsandslots.html Signals & Slots]
|-
|-
|Layouty
|Layouty
|[http://doc.qt.nokia.com/4.7/layout.html Layout Management], [http://doc.qt.nokia.com/4.7/widgets-and-layouts.html Widgets and Layouts], [http://doc.qt.nokia.com/4.7/examples-layouts.html Layout Examples]
|[https://doc.qt.io/qt-5/layout.html Layout Management], [https://doc.qt.io/qt-5/widgets-and-layouts.html Widgets and Layouts], [https://doc.qt.io/qt-5/examples-layouts.html Layout Examples]
|-
|-
|Widgety které Qt nabízí
|Widgety které Qt nabízí
|[http://doc.qt.nokia.com/4.7/gallery.html Qt Widget Gallery], [http://doc.qt.nokia.com/4.7/examples-widgets.html Widget Examples]
|[https://doc.qt.io/qt-5/gallery.html Qt Widget Gallery], [https://doc.qt.io/qt-5/examples-widgets.html Widget Examples]
|}
|}


== Odvozování vlastních widgetů od QWidgetu ==
== Odvozování vlastních widgetů od QWidgetu ==


Možná by bylo hezké dotázat se uživatele před ukončením aplikace, zdali opravdu chce aplikaci opustit. V tomto příkladě vytvoříme podtřídu [http://doc.qt.nokia.com/4.7/qwidget.html QWidgetu], které přidáme vlastní slot a následně ho napojíme na naše tlačítko 'Quit'.
Možná by bylo hezké dotázat se uživatele před ukončením aplikace, zdali opravdu chce aplikaci opustit. V tomto příkladě vytvoříme podtřídu [https://doc.qt.io/qt-5/qwidget.html QWidgetu], které přidáme vlastní slot a následně ho napojíme na naše tlačítko 'Quit'.


[[Image:http://doc.qt.nokia.com/4.7/images/gs3.png|Odvozujeme od QWidgetu]]
[[Image:https://web.archive.org/web/20140809121237if_/http://qt-project.org/doc/qt-5/images/gs3.png|Odvozujeme od QWidgetu]]


Podívejme se nyní na zdrojový kód
Podívejme se nyní na zdrojový kód
Line 129: Line 127:
};</code>
};</code>


Na začátku definice naší třídy (která přirozeně musí být podtřídou třídy [http://doc.qt.nokia.com/4.7/qobject.html QObject]. [http://doc.qt.nokia.com/4.7/qobject.html QObject]) musí být makro Q_OBJECT, to z ní učiní plnohotnotný QObject. To že je třída QObjectem jí dává specielní vlastnosti. Například se můžeme dotázat na název třídy či slotu za běhu programu. Je také možné zjistit parametry slotu a zavolat ho.
Na začátku definice naší třídy (která přirozeně musí být podtřídou třídy [https://doc.qt.io/qt-5/qobject.html QObject]. [https://doc.qt.io/qt-5/qobject.html QObject]) musí být makro Q_OBJECT, to z ní učiní plnohotnotný QObject. To že je třída QObjectem jí dává specielní vlastnosti. Například se můžeme dotázat na název třídy či slotu za běhu programu. Je také možné zjistit parametry slotu a zavolat ho.


Řádek 13 deklaruje slot quit(). Nyní můžeme quit() propojit se signály s odpovídajícím prototypem (libovolným bezparametrickým signálem).
Řádek 13 deklaruje slot quit(). Nyní můžeme quit() propojit se signály s odpovídajícím prototypem (libovolným bezparametrickým signálem).
Line 151: Line 149:
}</code>
}</code>


Jak jste mohli vidět v definici třídy, používáme ukazatele na naše [http://doc.qt.nokia.com/4.7/qobject.html QObjekty] (textEdit a quitButton). Zpravidla byste měli [http://doc.qt.nokia.com/4.7/qobject.html QObjekty] vždy alokovat na heapu a nikdy je kopírovat.
Jak jste mohli vidět v definici třídy, používáme ukazatele na naše [https://doc.qt.io/qt-5/qobject.html QObjekty] (textEdit a quitButton). Zpravidla byste měli [https://doc.qt.io/qt-5/qobject.html QObjekty] vždy alokovat na heapu a nikdy je kopírovat.


Viditelné stringy "obalujeme" do funkce [http://doc.qt.nokia.com/4.7/qobject.html#tr> tr()] a to z toho důvodu, kdybychom se v budoucnu rozhodli poskytovat naší aplikaci ve více jazykových mutacích. Nebudeme zacházet do detailů, ovšem pokud vás téma zajímá, můžete se podívat na odkaz Qt Linguist z následující tabulky.
Viditelné stringy "obalujeme" do funkce [https://doc.qt.io/qt-5/qobject.html#tr> tr()] a to z toho důvodu, kdybychom se v budoucnu rozhodli poskytovat naší aplikaci ve více jazykových mutacích. Nebudeme zacházet do detailů, ovšem pokud vás téma zajímá, můžete se podívat na odkaz Qt Linguist z následující tabulky.


=== Rozšiřující informace ===
=== Rozšiřující informace ===
|Téma|Odkaz|
|Téma|Odkaz|
|tr() a internacionalizace|[http://doc.qt.nokia.com/4.7/linguist-manual.html Qt Linguist Manual], [http://doc.qt.nokia.com/4.7/i18n-source-translation.html Writing SOurce Code for Translation], [http://doc.qt.nokia.com/4.7/linguist-hellotr.html Hello tr()] Example, [http://doc.qt.nokia.com/4.7/internationalization.html| Internationalization with Qt]
|tr() a internacionalizace|[https://doc.qt.io/qt-5/linguist-manual.html Qt Linguist Manual], [https://doc.qt.io/qt-5/i18n-source-translation.html Writing SOurce Code for Translation], [https://doc.qt.io/qt-5/linguist-hellotr.html Hello tr()] Example, [https://doc.qt.io/qt-5/internationalization.html| Internationalization with Qt]
|QObjekty a objektový model Qt (Základ pro porozumění Qt)|[http://doc.qt.nokia.com/4.7/object.html| Object Model]
|QObjekty a objektový model Qt (Základ pro porozumění Qt)|[https://doc.qt.io/qt-5/object.html| Object Model]
|qmake a systém překladu Qt|[http://doc.qt.nokia.com/4.7/qmake-manual.html| qmake Manual]
|qmake a systém překladu Qt|[https://doc.qt.io/qt-5/qmake-manual.html| qmake Manual]


== Vytváření .pro souboru ==
== Vytváření .pro souboru ==
Line 173: Line 171:


== Používání třídy QMainWindow ==
== Používání třídy QMainWindow ==
Mnoho aplikací bude mít prospěch z používání [http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindow], které má svůj vlastní layout kam můžete přidat menu, dokovací widgety, nástrojovou lištu a stavovou lištu. [http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindow] má centrální oblast která může obsahovat libovolný widget. V Našem případě tam umístíme naši oblast pro úpravu textu.
Mnoho aplikací bude mít prospěch z používání [https://doc.qt.io/qt-5/qmainwindow.html QMainWindow], které má svůj vlastní layout kam můžete přidat menu, dokovací widgety, nástrojovou lištu a stavovou lištu. [https://doc.qt.io/qt-5/qmainwindow.html QMainWindow] má centrální oblast která může obsahovat libovolný widget. V Našem případě tam umístíme naši oblast pro úpravu textu.
 
[[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|Používání třídy QMainWindow]]


Nyní se podívejme na novou definici třídy Notepad
Nyní se podívejme na novou definici třídy Notepad
Line 205: Line 201:
Přidáváme další dva sloty pro otevření a uložení dokumentu. Budou implementovány v následující sekci.
Přidáváme další dva sloty pro otevření a uložení dokumentu. Budou implementovány v následující sekci.


Často chceme, aby bylo možné vyvolat jediný slot několika widgety. Typický příklad představují položky menu a tlačítka na nástrojové liště. Pro usnadnění Qt nabízízí [http://doc.qt.nokia.com/4.7/qaction.html QAction], která může být předáná několika widgetům a být propojena se slotem. Například jak [http://doc.qt.nokia.com/4.7/qmenu.html QMenu] tak i [http://doc.qt.nokia.com/4.7/qtoolbar.html QToolBar] mohou vytvářet položky menu a nástrojová tlačítka z identických [http://doc.qt.nokia.com/4.7/qaction.html QAction] objektů. Za moment se podíváme jak to funguje.
Často chceme, aby bylo možné vyvolat jediný slot několika widgety. Typický příklad představují položky menu a tlačítka na nástrojové liště. Pro usnadnění Qt nabízízí [https://doc.qt.io/qt-5/qaction.html QAction], která může být předáná několika widgetům a být propojena se slotem. Například jak [https://doc.qt.io/qt-5/qmenu.html QMenu] tak i [https://doc.qt.io/qt-5/qtoolbar.html QToolBar] mohou vytvářet položky menu a nástrojová tlačítka z identických [https://doc.qt.io/qt-5/qaction.html QAction] objektů. Za moment se podíváme jak to funguje.
 
[[Image:https://web.archive.org/web/20140809121236if_/http://qt-project.org/doc/qt-5/images/gs4.png|Používání třídy QMainWindow]]


Stejně jako v předchozí definici, nastavujeme GUI v konstruktoru třídy Notepad
Stejně jako v předchozí definici, nastavujeme GUI v konstruktoru třídy Notepad
Line 231: Line 229:
}</code>
}</code>


Naše [http://doc.qt.nokia.com/4.7/qaction.html QAction] objekty jsou vytvořeny s textem který chceme zobrazit na widgetech kterým je předáme (v našem případě se jedná o položky v menu). Pokud bychom je zároveň chtěli přidat do nástrojové lišty, mohli bychom jim nastavit i [http://doc.qt.nokia.com/4.7/qicon.html ikony].
Naše [https://doc.qt.io/qt-5/qaction.html QAction] objekty jsou vytvořeny s textem který chceme zobrazit na widgetech kterým je předáme (v našem případě se jedná o položky v menu). Pokud bychom je zároveň chtěli přidat do nástrojové lišty, mohli bychom jim nastavit i [https://doc.qt.io/qt-5/qicon.html ikony].


Pokud nyní stiskneme položku v menu, spustí to danou akci a ta vyvolá příslušný slot.
Pokud nyní stiskneme položku v menu, spustí to danou akci a ta vyvolá příslušný slot.
Line 237: Line 235:
=== Rozšiřující informace ===
=== Rozšiřující informace ===
|Téma|Odkaz|
|Téma|Odkaz|
|Hlavní okna a jejich třídy|[http://doc.qt.nokia.com/4.7/mainwindow.html Application Main Window], [http://doc.qt.nokia.com/4.7/examples-mainwindow.html| Main Window Examples]
|Hlavní okna a jejich třídy|[https://doc.qt.io/qt-5/mainwindow.html Application Main Window], [https://doc.qt.io/qt-5/examples-mainwindow.html| Main Window Examples]
|MDI aplikace|[http://doc.qt.nokia.com/4.7/qmdiarea.html QMdiArea], [http://doc.qt.nokia.com/4.7/mainwindows-mdi.html| MDI Example]
|MDI aplikace|[https://doc.qt.io/qt-5/qmdiarea.html QMdiArea], [https://doc.qt.io/qt-5/mainwindows-mdi.html| MDI Example]


== Ukládání a načítání ==
== Ukládání a načítání ==
V tomto příkladě naimplementujeme funkčnost slotů open() a save(), které jsme přidali v předchozí definici.
V tomto příkladě naimplementujeme funkčnost slotů open() a save(), které jsme přidali v předchozí definici.


[[Image:http://doc.qt.nokia.com/4.7/images/gs5.png|Ukládání a načítání]]
[[Image:https://web.archive.org/web/20140809121237if_/http://qt-project.org/doc/qt-5/images/gs5.png|Ukládání a načítání]]


Začneme se slotem open():
Začneme se slotem open():
Line 262: Line 260:
}</code>
}</code>


Prvním krokem je dotázání se uživatele na název souboru, který chce otevřít. Qt nabízí [http://doc.qt.nokia.com/4.7/qfiledialog.html QFileDialog], což je dialog ve kterém uživatel může vybrat soubor. Obrázek výše zobrazuje tento dialog na Linuxové distribuci Kubuntu. Statická funkce [http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName> getOpenFileName()] zobrazí modální souborový dialog a neskončí dokud uživatel nevybere soubor. Vrací cestu k vybranému souboru, případně prázdný řetězec pokud uživatel dialog zrušil.
Prvním krokem je dotázání se uživatele na název souboru, který chce otevřít. Qt nabízí [https://doc.qt.io/qt-5/qfiledialog.html QFileDialog], což je dialog ve kterém uživatel může vybrat soubor. Obrázek výše zobrazuje tento dialog na Linuxové distribuci Kubuntu. Statická funkce [https://doc.qt.io/qt-5/qfiledialog.html#getOpenFileName> getOpenFileName()] zobrazí modální souborový dialog a neskončí dokud uživatel nevybere soubor. Vrací cestu k vybranému souboru, případně prázdný řetězec pokud uživatel dialog zrušil.


Pokud máme cestu k souboru, pokusíme se ho otevřít funkcí [http://doc.qt.nokia.com/4.7/qiodevice.html#open> open()]. Ta vrací true pokud bylo otevření úspěšné. Nebudeme zacházet do detailů co se zpracování chyb týče, ovšem můžete si přečíst články odkázané v sekci "Rozšiřující informace". Pokud soubor nemůže být otevřen, zobrazíme [http://doc.qt.nokia.com/4.7/qmessagebox.html QMessageBox] a zobrazíme dialog s chybovým hlášením (pro více informací si přečtěte dokumentaci třídy [http://doc.qt.nokia.com/4.7/qmessagebox.html QMessageBox]).
Pokud máme cestu k souboru, pokusíme se ho otevřít funkcí [https://doc.qt.io/qt-5/qiodevice.html#open> open()]. Ta vrací true pokud bylo otevření úspěšné. Nebudeme zacházet do detailů co se zpracování chyb týče, ovšem můžete si přečíst články odkázané v sekci "Rozšiřující informace". Pokud soubor nemůže být otevřen, zobrazíme [https://doc.qt.io/qt-5/qmessagebox.html QMessageBox] a zobrazíme dialog s chybovým hlášením (pro více informací si přečtěte dokumentaci třídy [https://doc.qt.io/qt-5/qmessagebox.html QMessageBox]).
Čtení dat je díky funcki [http://doc.qt.nokia.com/4.7/qiodevice.html#readAll> readAll()] triviální, ta vrátí veškerá data obsažená v souboru v [http://doc.qt.nokia.com/4.7/qbytearray.html QByteArray]. Funkce [http://doc.qt.nokia.com/4.7/qbytearray.html#constData> constData()] vrací veškerá data jako const char''' jenž [http://doc.qt.nokia.com/4.7/qstring.html QString] přebírá v jednom ze svých konstruktorů. Poté již obsah souboru snadno zobrazíme v oblasti pro úpravu textu. Po načtení soubor uzavřeme za použití [http://doc.qt.nokia.com/4.7/qiodevice.html#close> close()], tím předáme souborový deskriptor zpět operačnímu systému.
Čtení dat je díky funcki [https://doc.qt.io/qt-5/qiodevice.html#readAll> readAll()] triviální, ta vrátí veškerá data obsažená v souboru v [https://doc.qt.io/qt-5/qbytearray.html QByteArray]. Funkce [https://doc.qt.io/qt-5/qbytearray.html#constData> constData()] vrací veškerá data jako const char''' jenž [https://doc.qt.io/qt-5/qstring.html QString] přebírá v jednom ze svých konstruktorů. Poté již obsah souboru snadno zobrazíme v oblasti pro úpravu textu. Po načtení soubor uzavřeme za použití [https://doc.qt.io/qt-5/qiodevice.html#close> close()], tím předáme souborový deskriptor zpět operačnímu systému.


Nyní se podívejme na slot save().
Nyní se podívejme na slot save().
Line 284: Line 282:
}</code>
}</code>


Při ukládání obsahu oblasti pro úpravu textu do textového souboru používáme třídy [http://doc.qt.nokia.com/4.7/qtextstream.html QTextStream], která zaobaluje objekt třídy [http://doc.qt.nokia.com/4.7/qfile.html QFile]. Tento textový proud je schopen zapisovat [http://doc.qt.nokia.com/4.7/qstring.html QString] přímo do souboru; [http://doc.qt.nokia.com/4.7/qfile.html QFile] přijímá pouze surová data (typu char''') funkcí [http://doc.qt.nokia.com/4.7/qiodevice.html#write> write()] třídy [http://doc.qt.nokia.com/4.7/qiodevice.html QIODevice]
Při ukládání obsahu oblasti pro úpravu textu do textového souboru používáme třídy [https://doc.qt.io/qt-5/qtextstream.html QTextStream], která zaobaluje objekt třídy [https://doc.qt.io/qt-5/qfile.html QFile]. Tento textový proud je schopen zapisovat [https://doc.qt.io/qt-5/qstring.html QString] přímo do souboru; [https://doc.qt.io/qt-5/qfile.html QFile] přijímá pouze surová data (typu char''') funkcí [https://doc.qt.io/qt-5/qiodevice.html#write> write()] třídy [https://doc.qt.io/qt-5/qiodevice.html QIODevice]


=== Rozšiřující informace ===
=== Rozšiřující informace ===
Line 293: Line 291:
|-
|-
|Soubory a zařízení vstupu a výstupu
|Soubory a zařízení vstupu a výstupu
|[http://doc.qt.nokia.com/4.7/qfile.html QFile], [http://doc.qt.nokia.com/4.7/qiodevice.html QIODevice]
|[https://doc.qt.io/qt-5/qfile.html QFile], [https://doc.qt.io/qt-5/qiodevice.html QIODevice]
|}
|}

Latest revision as of 18:17, 3 December 2019

Začínáme programovat s Qt

Vítejte ve světe Qt — ve světe multiplatformního GUI toolkitu. V tomto tutoriálu si krok za krokem ukážeme jak naprogramovat aplikaci jako je Notepad, tímto způsobem vás naučíme základních dovedností. Po přečtení tohoto návodu byste měli být připraveni na čtení našich přehledů a API dokumentace a zároveň být schopni nalézt informace, které můžete uplatnit ve vámi vyvíjených aplikacích.

Ahoj Notepade

V tomto úvodním příkladu vytvoříme a zobrazíme oblast pro úpravu textu. Takto vypadá nejjednodušší možný Qt program.

Ahoj Notepade

A toto je jeho zdrojový kód:

#include <QApplication>
#include <QTextEdit>

int main(int argv, char *'''args)
{
 QApplication app(argv, args);

 QTextEdit textEdit;
 textEdit.show();

 return app.exec();
}

Nyní si tento zdrojový kód řádek po řádku projdeme. V prvních dvou řádcích vkládáme hlavičkové soubory pro QApplication a QTextEdit, což jsou přávě ty třídy, které pro tento příklad potřebujeme. Názvy všech Qt hlavičkových souborů se shodují s názvy tříd které jsou v nich deklarovány.

Na řádku 6 vytváříme objekt třídy QApplication. Tento objekt spravuje prostředky celé aplikace a je vyžadován pro funkčnost všech Qt programů mající GUI. Jako parametry potřebuje argv a args, potože Qt samo od sebe přijímá několik argumentů příkazové řádky.

Řádek 8 vytváří objekt třídy QTextEdit. Oblast pro úpravu textu je vizuální prvek GUI. V Qt takovéto elementy nazýváme widgety. Příklady dalších widgetů jsou například posuvníky, štítky, přepínače, atp. Widget může být zároveň kontejnerem pro další widgety; příkladem budiž hlavní okno aplikace či dialog.

Řádek 9 zobrazí oblast pro úpravu textu na obrazovce ve vlastním okně. Vzhledem k tomu, že widgety mohou složit i jako kontejnery (například QMainWindow, který obsahuje nástrojovou lištu, menu, stavový řádek a několik dalších widgetů), je možné zobrazit widget ve vlastním okně. Widgety jsou implicitně skryty; o zobrazení se stará právě metoda show()).

Řádek 11 spustí hlavní smyčku eventů aplikace. Dokud aplikace beží, jejím widgetům jsou zasílány eventy. Příkladem eventů jsou stisknutí tlačítek myši a klávesnice. Jakmile napíšete text do dříve zmíněné oblasti pro úpravu textu, ta obdrží eventy informující o stisknutí kláves a reaguje vykreslením příslušného textu.

Pro spuštění aplikace, otevřete příkazovou řádku, přejděte do adresáře kde máte její zdrojový soubor a napište následující příkazy.

qmake -project
qmake
make

Ty vytvoří spustitelný soubor v daném adresáři (na systémech windows bude možná třeba použít nmake namísto make. Také spustitelné soubory se budou nacházet buďto v podadresáři release nebo debug). qmake je Qt nástroj pro sestavování projektů vyžadující konfigurační soubor. Tento konfigurační soubor za nás qmake sám vygeneruje, když ho spustíme s přepínačem -project. Z daného konfiguračního souboru (s příponou .pro) qmake vytvoří makefile, která za vás program sestaví. Na to jak si můžete vytvořit vlastní .pro soubor se podíváme později.

Rozšiřující informace

|Téma|Odkaz| |Widgety a gemoetrie okna|Window and Dialog Widgets |Eventy a jejich zpracování|The Event System

Přídání tlačítka 'Quit'

V reálné aplikaci budete běžně potřebovat více než jen jeden widget. Nyní přidáme QPushButton pod oblast pro úpravu textu. Toto tlačítko bude plnit funkci vypínače aplikace (společně se zavřením okna).

Ahoj Notepade

Nyní se podívejme na zdrojový kód

#include <QtGui>

int main(int argv, char'''*args)
{
 QApplication app(argv, args);

QTextEdit textEdit;
 QPushButton quitButton("Quit");

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

QVBoxLayout layout;
 layout.addWidget(&textEdit);
 layout.addWidget(&quitButton);

QWidget window;
 window.setLayout(&layout);

window.show();

return app.exec();
}

Na řádku 1 vkládáme QtGui, které obsahuje všechny Qt GUI třídy.

Řádek 10 používá Qt systém signálů a slotů a zajišťuje, že stisknutí tlačítka 'Quit' ukončí aplikaci. Slot je funkce, která může být vyvolána za běhu použitím jejího jména (jako doslovný řetězec). Signál je funkce, která když zavolána zavolá všechny sloty s ní propojené; tyto procedury nazýváme propojení slotu se signálem (to connect the slot to the signal) a vyslání signálu (to emit the signal).

quit() je slot třídy QApplication , který při zavolání ukončí aplikaci. clicked() je signál třídy, který QPushButton vyšle poté co je stisknut. Statická funkce QObject::connect() se stará o propojení signálu se slotem. SIGNAL () a SLOT() jsou dvě makra, která přebírají prototyp (type-signature) signálu a slotu k propojení.

Řádek 12 vytváří objekt třídy QVBoxLayout. Jak již bylo zmíňeno, widgety mohou obsahovat další wigety. Je také možné přímo nastavit meze (umístění a velikost) potomků widgetu (widgetů, které daný widget obsahuje). Layout spravuje meze svých potomků automaticky. Například QVBoxLayout umístí potomky vertikálně pod sebe.

Řádky 13 a 14 přidávájí do layoutu oblast na úpravu textu a tlačítko. Řádek 17 nastavuje nastaví widgetu hlavní layout.

Rozšiřující informace

Téma Odkaz
Signály a Sloty Signals & Slots
Layouty Layout Management, Widgets and Layouts, Layout Examples
Widgety které Qt nabízí Qt Widget Gallery, Widget Examples

Odvozování vlastních widgetů od QWidgetu

Možná by bylo hezké dotázat se uživatele před ukončením aplikace, zdali opravdu chce aplikaci opustit. V tomto příkladě vytvoříme podtřídu QWidgetu, které přidáme vlastní slot a následně ho napojíme na naše tlačítko 'Quit'.

Odvozujeme od QWidgetu

Podívejme se nyní na zdrojový kód

class Notepad : public QWidget
{
 Q_OBJECT

public:
 Notepad();

private slots:
 void quit();

private:
 QTextEdit *textEdit;
 QPushButton *quitButton;
};

Na začátku definice naší třídy (která přirozeně musí být podtřídou třídy QObject. QObject) musí být makro Q_OBJECT, to z ní učiní plnohotnotný QObject. To že je třída QObjectem jí dává specielní vlastnosti. Například se můžeme dotázat na název třídy či slotu za běhu programu. Je také možné zjistit parametry slotu a zavolat ho.

Řádek 13 deklaruje slot quit(). Nyní můžeme quit() propojit se signály s odpovídajícím prototypem (libovolným bezparametrickým signálem).

Namísto nastavování GUI a propojení slotu ve funkci main() provádíme tuto práci v konstruktoru třídy Notepad.

Notepad::Notepad()
{
 textEdit = new QTextEdit;
 quitButton = new QPushButton(tr("Quit"));

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

QVBoxLayout '''layout = new QVBoxLayout;
 layout->addWidget(textEdit);
 layout->addWidget(quitButton);

 setLayout(layout);

 setWindowTitle(tr("Notepad"));
}

Jak jste mohli vidět v definici třídy, používáme ukazatele na naše QObjekty (textEdit a quitButton). Zpravidla byste měli QObjekty vždy alokovat na heapu a nikdy je kopírovat.

Viditelné stringy "obalujeme" do funkce > tr() a to z toho důvodu, kdybychom se v budoucnu rozhodli poskytovat naší aplikaci ve více jazykových mutacích. Nebudeme zacházet do detailů, ovšem pokud vás téma zajímá, můžete se podívat na odkaz Qt Linguist z následující tabulky.

Rozšiřující informace

|Téma|Odkaz| |tr() a internacionalizace|Qt Linguist Manual, Writing SOurce Code for Translation, Hello tr() Example, Internationalization with Qt |QObjekty a objektový model Qt (Základ pro porozumění Qt)|Object Model |qmake a systém překladu Qt|qmake Manual

Vytváření .pro souboru

Na ukázku si vytvoříme vlastní .pro soubor namísto toho, který za nás vygenerovalo qmake -project.

HEADERS = notepad.h
SOURCES = notepad.cpp  main.cpp

Následující příkazy přeloží náš ukázkový projekt.

qmake
make

Používání třídy QMainWindow

Mnoho aplikací bude mít prospěch z používání QMainWindow, které má svůj vlastní layout kam můžete přidat menu, dokovací widgety, nástrojovou lištu a stavovou lištu. QMainWindow má centrální oblast která může obsahovat libovolný widget. V Našem případě tam umístíme naši oblast pro úpravu textu.

Nyní se podívejme na novou definici třídy Notepad

#include <QtGui>

class Notepad : public QMainWindow
{
 Q_OBJECT

public:
 Notepad();

private slots:
 void open();
 void save();
 void quit();

private:
 QTextEdit *textEdit;

 QAction *openAction;
 QAction *saveAction;
 QAction *exitAction;

 QMenu '''fileMenu;
};

Přidáváme další dva sloty pro otevření a uložení dokumentu. Budou implementovány v následující sekci.

Často chceme, aby bylo možné vyvolat jediný slot několika widgety. Typický příklad představují položky menu a tlačítka na nástrojové liště. Pro usnadnění Qt nabízízí QAction, která může být předáná několika widgetům a být propojena se slotem. Například jak QMenu tak i QToolBar mohou vytvářet položky menu a nástrojová tlačítka z identických QAction objektů. Za moment se podíváme jak to funguje.

Používání třídy QMainWindow

Stejně jako v předchozí definici, nastavujeme GUI v konstruktoru třídy Notepad

Notepad::Notepad()
{
 saveAction = new QAction(tr("&Open"), this);
 saveAction = new QAction(tr("&Save"), this);
 exitAction = new QAction(tr("E&xit"), this);

 connect(openAction, SIGNAL (triggered()), this, SLOT (open()));
 connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));
 connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));

 fileMenu = menuBar()->addMenu(tr("&File"));
 fileMenu->addAction(openAction);
 fileMenu->addAction(saveAction);
 fileMenu->addSeparator();
 fileMenu->addAction(exitAction);

 textEdit = new QTextEdit;
 setCentralWidget(textEdit);

 setWindowTitle(tr("Notepad"));
}

Naše QAction objekty jsou vytvořeny s textem který chceme zobrazit na widgetech kterým je předáme (v našem případě se jedná o položky v menu). Pokud bychom je zároveň chtěli přidat do nástrojové lišty, mohli bychom jim nastavit i ikony.

Pokud nyní stiskneme položku v menu, spustí to danou akci a ta vyvolá příslušný slot.

Rozšiřující informace

|Téma|Odkaz| |Hlavní okna a jejich třídy|Application Main Window, Main Window Examples |MDI aplikace|QMdiArea, MDI Example

Ukládání a načítání

V tomto příkladě naimplementujeme funkčnost slotů open() a save(), které jsme přidali v předchozí definici.

Ukládání a načítání

Začneme se slotem open():

QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
 tr("Text Files ('''.txt);;C++ Files ('''.cpp'''.h)"));

if (fileName != "") {
 QFile file(fileName);
 if (!file.open(QIODevice::ReadOnly)) {
 QMessageBox::critical(this, tr("Error"),
 tr("Could not open file"));
 return;
 }
 QString contents = file.readAll().constData();
 textEdit->setPlainText(contents);
 file.close();
}

Prvním krokem je dotázání se uživatele na název souboru, který chce otevřít. Qt nabízí QFileDialog, což je dialog ve kterém uživatel může vybrat soubor. Obrázek výše zobrazuje tento dialog na Linuxové distribuci Kubuntu. Statická funkce > getOpenFileName() zobrazí modální souborový dialog a neskončí dokud uživatel nevybere soubor. Vrací cestu k vybranému souboru, případně prázdný řetězec pokud uživatel dialog zrušil.

Pokud máme cestu k souboru, pokusíme se ho otevřít funkcí > open(). Ta vrací true pokud bylo otevření úspěšné. Nebudeme zacházet do detailů co se zpracování chyb týče, ovšem můžete si přečíst články odkázané v sekci "Rozšiřující informace". Pokud soubor nemůže být otevřen, zobrazíme QMessageBox a zobrazíme dialog s chybovým hlášením (pro více informací si přečtěte dokumentaci třídy QMessageBox). Čtení dat je díky funcki > readAll() triviální, ta vrátí veškerá data obsažená v souboru v QByteArray. Funkce > constData() vrací veškerá data jako const char jenž QString přebírá v jednom ze svých konstruktorů. Poté již obsah souboru snadno zobrazíme v oblasti pro úpravu textu. Po načtení soubor uzavřeme za použití > close(), tím předáme souborový deskriptor zpět operačnímu systému.

Nyní se podívejme na slot save().

QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "",
 tr("Text Files ('''.txt);;C++ Files ('''.cpp '''.h)"));

if (fileName != "") {
 QFile file(fileName);
 if (!file.open(QIODevice::WriteOnly)) {
 // error message
 } else {
 QTextStream stream(&file);
 stream << textEdit->toPlainText();
 stream.flush();
 file.close();
 }
}

Při ukládání obsahu oblasti pro úpravu textu do textového souboru používáme třídy QTextStream, která zaobaluje objekt třídy QFile. Tento textový proud je schopen zapisovat QString přímo do souboru; QFile přijímá pouze surová data (typu char) funkcí > write() třídy QIODevice

Rozšiřující informace

Téma Odkaz
Soubory a zařízení vstupu a výstupu QFile, QIODevice