Práca s formulárom

Z Kiwiki
Skočit na navigaci Skočit na vyhledávání

Spracoval

Ing. Dušan Zervan


Formulár

V bežnom formulári budeme používať predovšetkým objekt typu TEdit ako klasickú "kolonku" na zadanie krátkeho 1-riadkového textu. Keďže vo formulári býva týchto prvkov spravidla viac, je rozumné nazývať ich prehľadne, napr. EditMeno, EditPriezvisko (meno akéhokoľvek objektu je určené vlastnosťou Name). Je tiež vhodné, aby po spustení programu boli tieto objekty prázdne (bez textu), preto mu zmažeme hodnotu vlastnosti Text.

V používateľsky prívetivom programe nesmie byť žiaden neoznačený prvok, preto je potrebné pred každý Edit pridať popisok typu TLabel! ZObrazený text predstavuje jeho vlastnosť Caption.

V prípade potreby zadávania dlhšieho textu využijeme textové pole typu TMemo, ktorý umožňuje zadávať mnohoriadkový text - stále iba neformátovaný (plain-text).

Pre odoslanie formulára bude slúžiť tlačidlo - objekt typu TButton, jeho viditeľný popis určuje vlastnosť Caption.

Spracovanie údajov z formulára

Údaje z formulára bývajú zvyčajne odosielané na spracovanie stlačením tlačidla - ide o udalosť OnClick objektu TButton.

Ku hodnotám zadaným do objektov TEdit sa dostaneme cez vlastnosť Text, teda napr. EditMeno->Text. Jedná sa o textový reťazec - na rozdiel od starého C++ a jeho poľa znakov char[] máme k dispozícii oveľa pohodlnejší AnsiString, s ktorým môžeme narábať podobne, ako s číselnou premennou int - teda porovnávať cez operátor == a spájať pomocou +. Pokiaľ má niektorý TEdit vyjadrovať výstupnú hodnotu (výsledok), nebude vhodné ju používateľom prepisovať - zamedzíme tomu nastavením vlastnosti ReadOnly.

Ak máme v niektorom TEdit číselnú hodnotu (napr. vek alebo rok), môžeme ho na číslo skonvertovať jednak klasickou formou príkazu StrToInt(text) - napr. int vek = StrToInt(EditVek->Text), ale v objektovom prostredí lepšie zapadne objektový prístup cez funkciu ToInt() objektu AnsiString - napr. int vek = EditVek->Text.ToInt(). Funkcie objektu sa v objektovom prostredí zvyknú nazývať pojmom "metóda", teda ide o metódu ToInt.

Problém nastane, keď bude zadaný nečíselný údaj a pokúsime sa ho prevádzať na číslo - program vtedy padne, čo by sa určite stať nemalo, preto musíme tomu predísť. Pokiaľ by šlo len o zistenie, či bola hodnota zadaná, stačí vlastnosť Text porovnať s prázdnym reťazcom, no vo všeobecnosti príde vhod vylepšená konverzná funkcia ToIntDef(hodnota), ktorá v prípade, že nie je možné text previezť na číslo, vráti hodnotu v parametri (tzv. implicitná alebo "default" hodnota). Je vhodné použiť takú hodnotu, ktorá v kontexte problému nemá význam, napr. číslo -1 pre vek. Program potom musí v ďalšom spracovaní túto hodnotu chápať ako neuvedenú a nepočítať s ňou! Typickým postupom je vypísanie chyby a presunutie kurzora do objektu, v ktorom je chyba, aby používateľ mohol ihneď chybu opraviť, napr.:

int vek = EditVek->Text.ToIntDef(-1);
if (vek < 0)
{
  ShowMessage("Chyba: Vek nemá číselnú hodnotu!");
  EditVek->SetFocus();
  return;
}

V uvedenom úryvku programu sú použité dve zaujímavé funkcie: ShowMessage(text) zobrazí okno s upozornením, a metóda SetFocus() akéhokoľvek viditeľného objektu presunie naň kurzor (tzv. fókus). Presun fókusu tam, kam v danej chvíli treba, patrí k základným požiadavkám na používateľsky prívetivý program.

Používateľská prívetivosť programu

Používateľsky prívetivý program musí nielen mať prehľadne usporiadané a označené prvky, ale musí aj čo najviac uľahčovať používateľovi jeho používanie. Pozrime sa na jednoduchý program pre krátenie zlomkov:

ukážka jednoduchého formulára

Chceli by sme dosiahnuť tieto ciele:

  1. po spustení programu bude kurzor nachystaný pre zadávanie čitateľa;
  2. stlačením Tab na klávesnici bude kurzor prechádzať vstupnými prvkami v tom poradí, ako sú zobrazené;
  3. stlačenie Enter po zadaní čitateľa presunie kurzor na zadávanie menovateľa;
  4. stlačenie Enter po zadaní menovateľa prevedie výpočet;
  5. po úspešnom vykonaní výpočtu sa kurzor opäť presunie na zadávanie čitateľa;
  6. ak je už zobrazený výsledok a zmení sa ktorákoľvek vstupná hodnota, výsledok sa ihneď zmaže.

Prvé dve požiadavky vyriešime naraz - totiž po spustení programu bude kurzor v tom prvku, ktorý je prvý v poradí. Ak by sme potrebovali toto zmeniť, využijeme nastavenie fókusu v udalosti OnShow samotného formulára. Poradie vstupných prvkov je možné určiť v návrhovom zobrazení - pravým tlačítkom klikneme na formulár a zvolíme Tab Order.

Tretiu požiadavku budeme nepochybne riešiť udalosťou vstupného prvku, do ktorého zadávame čitateľa (napr. s názvom EditCitatel) - budeme striehnuť, kedy dôjde k stlačeniu klávesu Enter. Po každom stlačení akéhokoľvek klávesu sa vyvolá udalosť OnKeyPress, už len v nej musíme zistiť, či sa jedná o Enter. Táto udalosť má ako vstupný parameter premennú Key, v ktorej je uvedený stlačený kláves, pričom Enter má kód '\r' - teda ak ho nájdeme, nastavíme fókus pre zadanie menovateľa:

void __fastcall TForm1::EditCitatelKeyPress(TObject *Sender, char &Key)
{
  if (Key == '\r')
    EditMenovatel->SetFocus();
}

Štvrtá požiadavka je takmer rovnaká, akurát na jej splnenie zavoláme udalosť stlačenia tlačidla z formulára:

void __fastcall TForm1::EditMenovatelKeyPress(TObject *Sender, char &Key)
{
  if (Key == '\r')
    ButtonVypocitajClick(Sender);
}

Piatu požiadavku ani nemá význam rozoberať, ide o jednoduché nastavenie fókusu vo funkcii pre výpočet, teda vo funkcii pre obsluhu udalosti stlačenia tlačidla.

Posledná požiadavka je tiež jednoduchá - riešiť ju budeme opäť udalosťou vstupného prvku, do ktorého zadávame čitateľa (EditCitatel), no tentokrát si nebudeme všímať stláčanie klávesov (pretože napr. šípky hodnotu nezmenia), ale priamo zmenu hodnoty - je to udalosť OnChange, v ktorej proste zmažeme výsledok:

void __fastcall TForm1::EditCitatelChange(TObject *Sender)
{
  EditVysledok->Text = "";
}

Pre menovateľ nemusíme vytvárať rovnakú udalosť, ale použijeme priamo udalosť čitateľa jej priradením v Object Inspector.