V minulém díle jsme skončili popisem vlastností komponent. U většiny komponent ale zpravidla nevystačíme s nastavením vlastností; potřebujeme, aby komponenta „vykazovala“, případně umožňovala nějakou činnost. K tomu slouží události.
V minulém díle jsme skončili popisem vlastností komponent. U většiny komponent ale zpravidla nevystačíme s nastavením vlastností; potřebujeme, aby komponenta „vykazovala“, případně umožňovala nějakou činnost. K tomu slouží události. Abychom správně reagovali na událost, musíme napsat programový kód. V něm snadno uděláme chybu, proto překlad projektu, ale především hledání a odstraňování chyb v kódu, je také velmi důležitým uměním.
Co jsou události
Když uživatel provede nějakou činnost s komponentou, například na ni klikne, generuje tato komponenta odpovídající událost. Někdy jsou události také generovány operačním systémem, bez zjevného uživatelova přispění.
Poznámka pro pokročilé uživatele:
Z technického hlediska jsou události Delphi vyvolávány poté, co dojde k obdržení zprávy operačního systému. Počet těchto událostí nemusí vždy nutně odpovídat počtu zpráv.
Podobně, jako existuje skupina vlastností, která je společná více (případně všem) komponentám, nalézáme v Delphi události, jež jsou dostupné více (všem) komponentám. Krátký popis nejpoužívanějších z nich (a případné tipy) viz následující tabulka:
Událost |
Kdy k ní dojde |
Poznámky |
OnChange |
při změně objektu (nebo jeho obsahu) |
Používána často u komponent typu Edit, Memo. Souvisí s read-only run-time vlastností Modified, která říká, byl-li obsah změněn. |
OnClick |
při kliknutí levým tlačítkem myši na komponentu |
Jedna z nejpoužívanějších komponent vůbec. |
OnDblClick |
při dvojkliknutí levým tlačítkem myši na komponentu |
|
OnEnter |
v okamžiku, kdy je komponenta aktivována |
Nejde o aktivaci formuláře (okna), například při přepnutí z jiné běžící aplikace, ale o aktivaci dané komponenty; tedy například kliknete-li do Editu, apod. |
OnExit |
v okamžiku, kdy je komponenta deaktivována |
Opak předchozí události; je např. vyvolána, skončíte-li zadávání do Editu, a kliknete jinam, apod. |
OnKeyDown |
v okamžiku, kdy je daná komponenta aktivní a uživatel stiskne klávesu |
Lze použít parametru Key, který říká, která klávesa byla stisknuta; lze rozlišovat současný stisk kláves Shift, Alt, Ctrl. |
OnKeyPress |
v okamžiku, kdy je daná komponenta aktivní a uživatel stiskne klávesu |
Rozdíl oproti OnKeyDown spočívá v tom, že parametr Key je typu char, událost je vyvolána jen při stisku kláves odpovídajících ASCII znakům (tedy ne Shift, F1, apod.). |
OnKeyUp |
v okamžiku, kdy daná komponenta je aktivní a uživatel uvolní klávesu |
Klíčovým momentem je uvolnění klávesy (pohyb nahoru); parametr Key je stejný jako u OnKeyDown. |
OnMouseDown |
v okamžiku, kdy uživatel stiskne některé tlačítko myši |
Zpravidla je poslána komponentě, která leží pod kurzorem myši. |
OnMouseMove |
v okamžiku, kdy uživatel pohne myší nad komponentou |
|
OnMouseUp |
v okamžiku, kdy uživatel uvolní některé tlačítko myši |
Je-li současně stisknutých více tlačítek, OnMouseUp je generována vícekrát při uvolnění každého z nich. |
Události formuláře (okna)
Výše uvedené události jsou často používané a patří asi k nejdůležitějším, rád bych ale ještě zmínil některé unikátní události formuláře. Když budete mít v programu dvacet tlačítek, budete pravděpodobně ošetřovat dvacet událostí OnClick. Formulář budete mít jeden, přesto je ošetření jediné vlastnosti OnActivate nebo OnCreate možná důležitější než dvacet „OnClicků“.
Událost |
Kdy k ní dojde |
Poznámky |
OnActivate |
stane-li se okno aktivním |
Je generována, přepne-li se uživatel do okna z jiného okna téže aplikace, nikoliv z jiné aplikace. |
OnDeactivate |
přestane-li být okno aktivním |
Je generována, přepne-li se uživatel do jiného okna téže aplikace, nikoliv do jiné aplikace. |
OnClose, OnCloseQuery |
je-li formulář zavřen (Alt-F4, křížek v rohu, systémové menu…) |
Při zavírání formuláře je nejprve generována OnCloseQuery, poté OnClose. První se používá např. pro potvrzení („Chcete opravdu skončit?“) nebo pro výzvu k uložení dat. Nicméně i v OnClose je ještě šance zavření zabránit a pomocí parametrů lze okno třeba jen skrýt či minimalizovat. |
OnCreate, OnDestroy |
při vytvoření, resp. zrušení formuláře |
|
OnShow, OnHide |
při zobrazení, resp. skrytí formuláře |
Tato událost úzce souvisí s vlastností formuláře Visible. |
Formulář má nepochybně další důležité vlastnosti, nemůžeme však popisovat všechny.
Poznámka pro pokročilé uživatele:
Při vytváření viditelného formuláře (např. při startu aplikace, vlastnost Visible = true) , je sekvence generovaných událostí následující:
- OnCreate
- OnShow
- OnActivate
- OnPaint
V události OnDestroy by měly být zrušeny (Dispose) všechny objekty dynamicky vytvořené v OnCreate (New).
Jak pracovat s událostmi
Vlastní vložení reakcí na události je velmi jednoduché, problémy zpravidla nastávají až v okamžiku, kdy je třeba naprogramovat konkrétní akce. Vše si vysvětlíme na jednoduchém příkladu, který využijeme i v dalším textu při hledání chyb.
Vytvoříme jednoduchou aplikaci, která po svém otevření nastaví jako svůj titulek slovo „Události“. Bude obsahovat dvě tlačítka, na jednom se zobrazí nápis „Konec“ jen tehdy, když nad ním bude kurzor myši (to není zrovna chytré řešení a v reálných aplikacích jej příliš často nevyužívejte J.). Druhé tlačítko bude mít titulek „Vypočti“ a po jeho stisknutí proběhne jednoduchá smyčka (for cyklus).
- Vytvoříme novou aplikaci a umístíme na formulář dvě tlačítka. Titulek jednoho tlačítka (Caption) nastavíme na prázdný (prostě nic), druhého na „Vypočti“. Titulek okna necháme zatím beze změny. Tlačítka přejmenujeme (Name) na btnKonec, resp. btnVypocti, formulář na wndHlavni (tím se změní jeho titulek; nevadí, ignorujme to). Zmenšíme formulář – nastavíme výšku (Height) na 130 a šířku (Width) na 200. Pokud máte s těmito činnostmi problémy, přečtěte si předchozí díly seriálu, najdete tam jejich podrobný popis a ukázky.
- V Object Inspectoru si otevřeme hlavní okno (wndHlavni) a klikneme na záložku Events (události). Vybereme např. vlastnost OnCreate a dvakrát klikneme do políčka vedle ní. Otevře se nám okno Unit1.pas. Nyní budeme programovat obsluhu události. Na místo, kde bliká kurzor, napíšeme (je vhodné dodržet odsazení, např. 2 mezery nebo tabulátor) wndHlavni.Caption := `Události`; Středník na konci sice není velmi důležitý J (za posledním příkazem před Endem není v Pascalu nutný), ale vřele doporučuji jej uvést!
- Zařídíme, aby se na ukončovacím tlačítku zobrazoval titulek. Toho dosáhneme tak, že ošetříme událost formuláře wndHlavni OnMouseMove. Kód bude btnKonec.Caption := ``;
- Nyní nastavíme stejnou vlastnost (OnMouseMove) tlačítka btnKonec: btnKonec.Caption := `Konec`;
- Další akcí bude ošetření události OnClick tlačítka btnKonec: Application.Terminate; J
- Posledním úkolem je nastavit událost OnClick druhého tlačítka, tedy btnVypocti. Tam napíšeme krátký cyklus, který využijeme v dalším textu. Deklarujeme také celočíselné proměnné i, j. Celá procedura bude vypadat takto (tučně je kód, který píšeme my):
procedure TwndHlavni.btnVypoctiClick(Sender: TObject);
var
i, j: integer;
begin
j := 0;
for i := 1 to 10 do
j := j + 10;
end;
Hledáme chyby
Pokud vytvořenou aplikaci přeložíte a spustíte (doporučuji též uložit), bude pracovat správně. Takový ideální stav ale bohužel není dosažen vždy. Proto v Delphi nacházíme integrovaný debugger s množstvím ladicích nástrojů a nástrojů pro detekci chyb v kódu. Je jich opravdu dost, my se podíváme na několik nejpoužívanějších, které patří k těm jednodušším, přesto jsou vcelku výkonné.
Poznámka pro pokročilé uživatele:
Kdykoliv spustíte program v prostředí Delphi, běží vlastně v integrovaném debuggeru. Tím je zajištěna použitelnost breakpointů a všech dalších ladicích nástrojů. Trochu jiná je také reakce na výjimky v debuggeru a ve vlastním operačním systému.
Co si vlastně představit pod pojmem „chyby v kódu“? Chyby můžeme (velmi hrubě) rozdělit do dvou částí:
- chyby detekované překladačem,
- chyby, které překladač neobjeví.
Chybami, na které upozorní již překladač, se nebudeme zabývat. V takovém případě kurzor spočívá na řádce ve zdrojovém souboru, kde se chyba vyskytuje a je zobrazena chybová hláška. Kliknete-li na tuto hlášku a stisknete-li F1, vypíše se nápověda s podrobným popisem příslušné chyby.
Horší jsou zpravidla chyby, které překladač nedetekuje. V takovém případě program spustíte a žijete v přesvědčení, že běží správně. Pokud je chyba skutečně „vypečená“, program většinou běhá dobře a jen někdy, zřídkakdy jsou třeba výsledky výpočtu špatné. Pak nastává fáze ladění a známého „odvšivování“ (debugg).
Ladíme a odvšivujeme
Podotýkám, že následující text není
kompletním referenčním popisem příslušných nástrojů. Klade si za cíl jen seznámit začínající uživatele s nejběžnějšími možnostmi integrovaného debuggeru.
Všechny níže uvedené nástroje se nacházejí v hlavním menu v položce Run.
Krokování Trace Into
Trace Into je klasické krokování programu po jednotlivých řádkách. Nejsnáze jej vyvoláte klávesou F7 a jejím každým dalším stiskem se posune provádění programu o další řádku. Narazí-li se přitom na volání podprogramu, skočí se do něj a pokračuje se stejným způsobem řádku po řádce.
Krokování Step Over
Step Over je podobné krokování jako Trace Into, ale s tím rozdílem, že při nalezení volání podprogramu je tento vykonán jako jednolitý blok a není tedy prováděn po řádkách. Vyvolá se klávesou F8.
Run to Cursor
Nastavíte-li kurzor na kteroukoliv řádku v kódu a stisknete-li F4, program se normálně spustí a poběží až do řádky, na které byl kurzor. Pak se provádění zastaví.
Breakpoints
Breakpoint (bod přerušení) funguje tak, že řeknete Delphi, aby běh programu zastavil v určeném bodě. Běžným použitím je nastavení breakpointu na některou řádku v kódu. Pak program spustíte (F9) a jakmile se vykonávání programu dostane na danou řádku, je zastaveno a vy můžete používat další nástroje, např. prohlížení obsahu proměnných, apod. – viz dále. Breakpointů můžete mít ve zdrojovém kódu nastaveno více najednou. Dostanete je do svého programu např. tak, že najedete na příslušnou řádku kurzorem a v menu najdete Run – Add Breakpoint… (ve verzi 3) nebo Run – Add Breakpoint – Source Breakpoint (ve verzi 5). Breakpointů existuje více typů, ale o tom se prozatím netřeba šířit.
Watch
Jedním z mnoha významů slova Watch je „číhat“. Myslím, že celkem vystihuje to, co se s nástrojem Watch často dělá. Zvolíte si některou (i nejednu) z proměnných (nebo libovolný výraz), breakpointem (nebo F4) se dostanete na začátek „problematického“ bloku a třeba krokováním se posouváte řádku po řádce a stále sledujete obsah dané proměnné (eventuálně hodnotu zadaného výrazu). Číháte na okamžik, kdy hodnota začne být podezřelá nebo vyloženě špatná, a tak se doberete původu chyby. Watches naleznete v menu Run – Add Watch… (nebo pomocí zkratky Ctrl-F5).
Evaluate/Modify
Tímto nástrojem můžete za běhu prohlížet, ale především měnit hodnoty výrazů, proměnných či vlastností. Je to výborný nástroj třeba v okamžiku, kdy chcete zjistit, jak by se program choval, kdyby v tom íčku nebyla sedmička, ale dva tisíce. Evaluate/Modify se skrývá v menu Run – Evaluate/Modify… (nebo Ctrl-F7).
Poznámka pro pokročilé uživatele:
Jediné, v čem Evaliate/Modify odmítne spolupracovat, je použití výrazu obsahující lokální nebo statické proměnné, které nejsou přístupné z daného místa; a dále funkční volání.
Co když zamrznete?
V průběhu ladění dojde občas k zamrznutí programu, nebo se prostě dostanete do situace, kdy chcete ladění přerušit a začít znovu. V takovém případě použijte příkaz Run – Program Reset (nebo Ctrl-F2).
Vyzkoušejte a vymyslete
Vyzkoušejte si použití zmíněných nástrojů na programu, který jsme vytvořili výše. Nebude to snadné, protože v něm není příliš co zkoumat (a nač číhat J), ale pro seznámení se zmíněnými nástroji postačuje.
Budete-li chtít sami sobě, případně někomu z vašich blízkých dokázat, že se z vás skutečně stává Delphi – expert, zamyslete se nad následující otázkou: umístíte-li breakpoint třeba na řádku j := j + 10;
breakpoint nezabere a program se na dané řádce nezastaví (přestože by měl, a to nejednou). A co je ještě tajuplnější – když třeba tělo for cyklu rozšíříte o podmínku if j = 40 then
wndHlavni.color := clRed;
Breakpoint ponechaný na původním místě najednou zabere! Víte, proč tomu tak je? Důvod prozradím v dalším díle seriálu (pokud jej tedy některý aktivnější Delphař nenapíše do příspěvku pod článek :).
Příště knihovna vizuálních komponent a standardní boxy
Po absolvování dnešního dílu už umíme vytvořit aplikaci, umístit na formulář komponenty, nastavit jejich vlastnosti, ošetřit jejich události a umíme také najít chybu, která se schovala do kódu. V příštím díle se podrobněji podíváme na knihovnu vizuálních komponent a na standardní dialogové boxy (jednoduché dialogy) pro výpis krátké informace s možností uživatelské interakce typu „ano, ne, storno“.