PHP-GTK

Tutorial (čtvrtý díl)

Signály, příklad jednoduché aplikace

Doposud jsme stále pracovali s aplikacemi, které nic užitečného nedělaly. Nezpracovávaly žádná data od uživatele. Nyní tedy přistupme k tvorbě nějakého smysluplného programu. Základem řízení zpracování dat v aplikaci PHP-GTK jsou tzv. signály. Kdo někdy programoval v JavaScriptu tak ví, že tam existují události, které když nastanou, tak spustí nějakou funkci. Signály v PHP-GTK jsou v principu tímtéž co události JavaScriptu. Jakmile je signál vyvolán, spustí se funkce, která provede požadované úkony. Asi nejběžnějším signálem je clicked, tento signál je vyslán v okamžiku kdy klikneme na widget, ke kterému je obsluha signálu připojena. Možná jste to doposud nevěděli, ale jeden signál zpracováváme téměř ve všech předchozích ukázkách kódu. Je to signál destroy, který je vyslán při zavření okna. Signál spustí funkci UkonciProgram(), která aplikaci korektně uzavře.

Nyní si zkusme vytvořit jednoduché okno s jedním tlačítkem, které poté co se na něj klikne, provede zápis do příkazového řádku.

Prvním krokem bude pochpitelně vytvoření samotného okna s jedním tlačítkem. To vše již bylo popisováno v minulých kapitolách, tudíž bychom to mohli lehce zvádnout. Nezapomeňme ošetřit i správné ukončení programu. Kód by měl tedy prozatím vypadat takto:

<?php

function UkonciProgram()
 {
 Gtk::main_quit();
 }

$okno = new GtkWindow();
$okno->set_title("signál click");
$okno->set_size_request(300,200);
$okno->connect_simple("destroy","UkonciProgram");

$tlacitko = new GtkButton("zapiš na příkazový řádek");

$box = new GtkVBox();
$box->pack_start($tlacitko,false);

$okno->add($box);

$okno->show_all();

Gtk::main();

?>
   
    

Druhým krokem je napsání funkce, která zápis na příkazový řádek provede. Budeme k tomu potřebovat nic složitějšího, než klasický příkaz echo():

function Zapis()
 {
 echo("zapis na prikazovy radek\r\n");
 }

    

Posledním krokem je připojení obsluhy signálu clicked k tlačítku. To provedeme pomocí metody connect_simple, které doplníme dva parametry, a to typ signálu, což je v našem případě clicked a pak název funkce, která provede zápis na příkazový řádek, tedy Zapis;
Doplněný zdrojový kód bude takovýto:

<?php

function UkonciProgram()
 {
 Gtk::main_quit();
 }

// funkce, ktera provede zapis do prikazoveho radku
function Zapis()
 {
 echo("zapis na prikazovy radek\r\n");
 }

$okno = new GtkWindow();
$okno->set_title("signál click");
$okno->set_size_request(300,200);
$okno->connect_simple("destroy","UkonciProgram");

$tlacitko = new GtkButton("zapiš na příkazový řádek");
$tlacitko->connect_simple("clicked","Zapis");     // pripojeni obsluhy udalosti

$box = new GtkVBox();
$box->pack_start($tlacitko,false);

$okno->add($box);

$okno->show_all();

Gtk::main();

?>
    

V případě že program spustíme, tak po každém i opakovaném kliknutí na tlačítko, by se měla na příkazovém řádku objevit věta zapis na prikazovy radek.

Teď si vytvoříme aplikaci, která pomocí textového vstupu vezme od uživatele číslo, k němu přičte jedničku a výsledek zapíše do příkazového řádku. Budeme vycházet z naší předchozí aplikace, jen ji rozšíříme o widget typu GtkEntry. To co zapíšeme do vstupu se bude načítat metodou get_text().

Zde je kód:

<?php

function UkonciProgram()
 {
 Gtk::main_quit();
 }

// funkce, ktera provede nacte cislo ze vstupu,
// pricte k nemu jednicku a vysledek vypise na prikazovy radek
function Zapis()
 {
 $hodnota = $GLOBALS['vstup']->get_text(); // nacteni textu ze vstupu
 $hodnota++;
 echo($hodnota." \r\n");
 }

$okno = new GtkWindow();
$okno->set_title("signál click");
$okno->set_size_request(300,200);
$okno->connect_simple("destroy","UkonciProgram");

$tlacitko = new GtkButton("zapiš na příkazový řádek");
$tlacitko->connect_simple("clicked","Zapis");    // pripojeni obsluhy udalosti

$vstup = new GtkEntry();


$box = new GtkVBox();
$box->set_border_width(10);
$box->set_spacing(10);
$box->pack_start($tlacitko,false);
$box->pack_start($vstup,false);

$okno->add($box);

$okno->show_all();

Gtk::main();

?>
    

Pohled na aplikaci:

PHP-GTK screenshot

Pro výukové účely může být zapisování hodnot z okna do příkazového řádku jistě přínosné, je ale zřejmé, že výstup budeme chtít zobrazit přímo v okně. Právě takovou aplikaci si nyní ukážeme. Vyjdeme opět z té předchozí, přičemž ji doplníme widgetem typu GtkLabel, do něhož se zobrazí výsledek výpočtu. Ve funkci Zapis() odstraníme řádek s příkazem echo, a namísto něj použijeme na objektu popisek metodu set_text(), které předáme vypočítaný výsledek. Ten se nyní zobrazí přímo v okně.

Zde je celý kód:

<?php

function UkonciProgram()
 {
 Gtk::main_quit();
 }

// funkce, ktera provede nacte cislo ze vstupu,
// pricte k nemu jednicku a vysledek vypise do popisku
function Zapis()
 {
 $hodnota = $GLOBALS['vstup']->get_text(); // nacteni textu ze vstupu
 $hodnota++;
 $GLOBALS['popisek']->set_text("Výsledek je: ".$hodnota);
 }

$okno = new GtkWindow();
$okno->set_title("signál click");
$okno->set_size_request(300,200);
$okno->connect_simple("destroy","UkonciProgram");

$tlacitko = new GtkButton("zapiš do okna výsledek");
$tlacitko->connect_simple("clicked","Zapis");    // pripojeni obsluhy udalosti

$vstup = new GtkEntry();

$popisek = new GtkLabel(" ");

$box = new GtkVBox();
$box->set_border_width(10);
$box->set_spacing(10);
$box->pack_start($tlacitko,false);
$box->pack_start($vstup,false);
$box->pack_start($popisek,false);

$okno->add($box);

$okno->show_all();

Gtk::main();

?>
    

A takto musí vypadat výsledek naší snahy:

PHP-GTK screenshot

Při prozkoumání výše uvedeného kódu vás možná napadne, zda-li by nebylo lepší předat funkci Zapis() objekty jako parametry při jejím volání, než je "vytahovat" z pole $GLOBALS. Takový postup je možný. Objekty, které chcete předat zapíšete jako další parametry funkce connect_simple(). Příklad:

$tlacitko->connect_simple("clicked","Zapis",$vstup,$popisek);

 

Další signály

Doposud jsme pracovali jen se dvěma typy signálů. Byl jím destroy (zavření okna) a clicked (kliknutí). Signálů je ale pochopitelně mnohem více, přičemž je nutno respektovat, že každý objekt má svou sadu signálů, které může "vyslat". Na objektu okna můžeme například získat signál destroy, ale nezískáme signál clicked. Jakou kolekci signálů můžeme u daného objektu obsloužit, to nalezneme v oficiální dokumentaci. Pro představu se podívejte do tabulky níže, která obsahuje možné signály u některých objektů.

Tabulka signálů u vybraných objektů
GtkWindowGtkButtonGtkTextView
Signály
activate-default
activate-focus
frame-event
keys-changed
move-focus
set-focus
activate
clicked
enter
leave
pressed
released
backspace
copy-clipboard
cut-clipboard
delete-from-cursor
insert-at-cursor
move-cursor
move-focus
move-viewport
page-horizontally
paste-clipboard
populate-popup
select-all
set-anchor
set-scroll-adjustments
toggle-overwrite
Společné signály:
add, check-resize, remove, set-focus-child
accel-closures-changed, button-press-event, button-release-event, can-activate-accel, child-notify, client-event, configure-event, delete-event, destroy-event, direction-changed, drag-begin, drag-data-delete, drag-data-get, drag-data-received, drag-drop, drag-end, drag-leave, drag-motion, enter-notify-event, event, event-after, expose-event, focus, focus-in-event, focus-out-event, grab-focus, grab-notify, hide, hierarchy-changed, key-press-event, key-release-event, leave-notify-event, map, map-event, mnemonic-activate, motion-notify-event, no-expose-event, parent-set, popup-menu, property-notify-event, proximity-in-event, proximity-out-event, realize, screen-changed, scroll-event, selection-clear-event, selection-get, selection-notify-event, selection-received, selection-request-event, show, show-help, size-allocate, size-request, state-changed, style-set, unmap, unmap-event, unrealize, window-state-event, destroy