Kurs PHP-GTK cz. 2
Już minęło sporo czasu od pojawienia się pierwszej części kursu PHP-GTK. Chciałem mocno przeprosić za to, że musieliście czekać, niestety w sporej mierze to wina mojego lenistwa…
Dzisiaj zajmiemy się czymś bardziej skomplikowanym. Stworzymy formularz logowania, który pokaże komunikat błędu jeśli wpiszemy złe hasło/login.
Na początku tworzymy nowy obiekt-okno, nadajemy mu tytuł, oraz tworzymy proste dowiązanie przerywające główną pętlę (Gtk::main). Później tworzymy dwa pola, do których będziemy mogli wpisać login i hasło. Podobnie jak w wypadku labela tworzymy dwie zmienne, które będą po prostu obiektami. Dodatkowo do tych pól stwórzmy etykietki, aby rozróżnić oba pola. Zwróćcie uwagę, że dodano jeszcze drugi parametr. Jest on opcjonalny, a gdy jest ustawiony na true, to literka przed którą będzie znak ‘_’, będzie podkreślona. Pozostało nam jeszcze stworzenie dwóch przycisków – “Login” i “Cancel”. W odróżnieniu od GtkLabel(), w przypadku GtkButton() nie musimy podawać drugiego parametru aby kolejna litera po ‘_’ była podkreślona. Teraz ustawimy połączenie pomiędzy GtkLabel, a GtkEntry. Ktoś się spyta, co to takiego? Już tłumaczę. To podkreślenie, które ustwiliśmy jest niczym innym jak skrótem klawiszowym. Po wciśnięciu kombinacji [Alt]+[u] pole Username zostanie aktywowane, podobnie jest z drugim polem. Aby stworzyć takie połączenie wykorzystujemy metodę set_mnemonic_widget. Pozostaje nam jeszcze najważniejsze. Ustawienie odpowiednich zdarzeń, które muszą nastąpić po wciśnięciu na Buttony. Po wciśnięciu “Cancel” program po prostu się wyłączy. Po wciśnięciu “Login” zostanie wywołana (jeszcze nie opisana) funkcja “login”, zmienne $wnd, $txtUsername, $txtPassword są po prostu parametrami przesyłanymi do funkcji. Już wcześniej wspominałem, że okno może trzymać bezpośrednio tylko jeden widżet. Rozwiązaniem są różne kontenery, które wszystko przetrzymują wewnątrz, a potem są “doklejane” do głównego okna. W tym wypadku posłużymy się GtkTable, które w przejrzysty sposób utrzyma nasze widżety (zmienna $lblCredit, będzie jedynie przechowywała krótki komunikat). Aby zamieścić nasze widżety w tabelkę należy wykonać coś takiego: Niestety umieszczanie elementów w tabeli wydaje się IMO wyjątkowo udziwnione. Żeby to jakoś ułatwić, postaram się króciutko wyjaśnić co oznaczają kolejne parametry. void attach(GtkWidget child, int left_attach, int right_attach, int top_attach, int bottom_attach [, GtkAttachOptions xoptions = Gtk::EXPAND|Gtk::FILL [, GtkAttachOptions yoptions = Gtk::EXPAND|Gtk::FILL [, int xpadding = Gtk::EXPAND|Gtk::FILL [, int ypadding = Gtk::EXPAND|Gtk::FILL]]]]); Taki jest początek opisu tej metody. Nie chcę straszyć nikogo także wytłumaczę tylko czym są te cyferki int left_attach – oznacza miejsce od lewej strony Możliwe, że źle zrozumiałem sposób umiejscowienia w tabelce elementów, także poprawcie mnie jeśli się mylę. Przyciski dostaną swój własny kontener. Stworzyliśmy dwa osobne kontenery, ale główne okno, może mieć “przyczepiony” tylko jeden widżet, także oba kontenery dodamy do kolejnego. Dopiero teraz możemy dodać nasze widżety na główne okno (konkretniej dodajemy kontener, który przechowuje wszystkie widżety). Teraz pozostaje nam zapis funkcji logowania. Jeśli jakieś z pól pozostanie puste, wyświetli się komunikat o błędzie. Jeśli uda nam się zalogować to dostaniemy komunikat, że wszystko jest ok, po czym program się wyłączy. Aby wyciągnąć zawartość pól “Username” i “Password”, posługujemy się metodą get_text() dołączoną do klasy GtkEntry. Poprawność wpisanego tekstu sprawdzamy poprzez zwykłe funkcje PHP (nie zapominajcie, że to jest tylko dodatek do PHP ;-] ). W celu wyświetlenia okna dialogowego wystarczy wpisać: Na koniec załączam gotowy kod (można go również pobrać z phpfi): Przypominam, że póki co ten kurs jest jedynie tłumaczeniem oficjalnego kursu, którego można znaleźć na stronie php.net
Screeny
Zaczynamy
<?php
$wnd = new GtkWindow();
$wnd->set_title('Login');
$wnd->connect_simple('destroy', array('gtk', 'main_quit'));
?>
$txtUsername = new GtkEntry();
$txtPassword = new GtkEntry();
$lblUsername = new GtkLabel('_Username', true);
$lblPassword = new GtkLabel('_Password', true);
$btnLogin = new GtkButton('_Login');
$btnCancel = new GtkButton('_Cancel');
$lblUsername->set_mnemonic_widget($txtUsername);
$lblPassword->set_mnemonic_widget($txtPassword);
$btnCancel->connect_simple('clicked', array($wnd, 'destroy'));
$btnLogin ->connect_simple('clicked', 'login', $wnd, $txtUsername, $txtPassword);
$tbl = new GtkTable(3, 2);
$tbl->attach($lblCredit, 0, 2, 0, 1);
$tbl->attach($lblUsername, 0, 1, 1, 2);
$tbl->attach($txtUsername, 1, 2, 1, 2);
$tbl->attach($lblPassword, 0, 1, 2, 3);
$tbl->attach($txtPassword, 1, 2, 2, 3);
int right_attach – oznacza miejsce od prawej strony
int top_attach – oznacza miejsce od góry
int bottom_attach – oznacza miejsce od dołu
$bbox = new GtkHButtonBox();
$bbox->set_layout(Gtk::BUTTONBOX_EDGE);
$bbox->add($btnCancel);
$bbox->add($btnLogin);
$vbox = new GtkVBox();
$vbox->pack_start($tbl);
$vbox->pack_start($bbox);
$wnd->add($vbox);
$wnd->show_all();
Gtk::main();
$strUsername = $txtUsername->get_text();
$strPassword = $txtPassword->get_text();
$dialog = new GtkMessageDialog($wnd, Gtk::DIALOG_MODAL, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, $errors);
$dialog->set_markup("W I A D O M O S C");
$dialog->run();
$dialog->destroy();
<?php
if (!class_exists('gtk')) {
die("Please load the php-gtk2 module in your php.ini\r\n");
}
/**
* Ta funkcja zostaje wywołana po kliknieciu buttona "Login"
*
* @param GtkWindow $wnd Okno logowania, potrzebne, zeby je pozniej
* zamknac
* @param GtkEntry $txtUsername Pole tekstowe, potrzebny zeby wyciagnac
* tekst
* @param GtkEntry $txtPassword Tak samo jak wyzej
*/
function login(GtkWindow $wnd, GtkEntry $txtUsername, GtkEntry $txtPassword)
{
//pobranie wartosci pol tekstowych
$strUsername = $txtUsername->get_text();
$strPassword = $txtPassword->get_text();
//sprawdzanie potrzebnych rzeczy
$errors = null;
if (strlen($strUsername) == 0) {
$errors .= "Brakuje nazwy uzytkownika.\r\n";
}
if (strlen($strPassword) == 0) {
$errors .= "Brakuje hasla.\r\n";
}
if ($errors !== null) {
//Jesli byl przynajmniej blad to powinno sie pokazac okno dialogowe
$dialog = new GtkMessageDialog($wnd, Gtk::DIALOG_MODAL,
Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, $errors);
$dialog->set_markup(
"Wystapily pewne problemy:\r\n"
. "<span foreground='red'>" . $errors . "</span>"
);
$dialog->run();
$dialog->destroy();
} else {
$msg = "Witaj $strUsername!\r\n";
$msg .= "Twoje magiczne haslo to: $strPassword ;-]";
$dialog = new GtkMessageDialog($wnd, Gtk::DIALOG_MODAL, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK, $msg);
$dialog->set_markup($msg);
$dialog->run();
$dialog->destroy();
$wnd->destroy();
}
}
$wnd = new GtkWindow();
$wnd->set_title('Login');
$wnd->connect_simple('destroy', array('gtk', 'main_quit'));
// stworzenie pol tekstowych
$txtUsername = new GtkEntry();
$txtPassword = new GtkEntry();
// stworzenie etykiet
$lblUsername = new GtkLabel('_Username', true);
$lblPassword = new GtkLabel('_Password', true);
$lblCredit = new GtkLabel('Please login');
// stworzenie buttonow
$btnLogin = new GtkButton('_Login');
$btnCancel = new GtkButton('_Cancel');
// ustawienie skrotow klawiszowych
$lblUsername->set_mnemonic_widget($txtUsername);
$lblPassword->set_mnemonic_widget($txtPassword);
// polaczenie zdarzen
$btnCancel->connect_simple('clicked', array($wnd, 'destroy'));
$btnLogin ->connect_simple('clicked', 'login', $wnd, $txtUsername, $txtPassword);
// stworzenie tabelki
$tbl = new GtkTable(3, 2);
$tbl->attach($lblCredit, 0, 2, 0, 1);
$tbl->attach($lblUsername, 0, 1, 1, 2);
$tbl->attach($txtUsername, 1, 2, 1, 2);
$tbl->attach($lblPassword, 0, 1, 2, 3);
$tbl->attach($txtPassword, 1, 2, 2, 3);
// kontener na przyciski
$bbox = new GtkHButtonBox();
$bbox->set_layout(Gtk::BUTTONBOX_EDGE);
$bbox->add($btnCancel);
$bbox->add($btnLogin);
// kontener przechowujacy tabelke i buttony
$vbox = new GtkVBox();
$vbox->pack_start($tbl);
$vbox->pack_start($bbox);
$wnd->add($vbox);
$wnd->show_all();
Gtk::main();
?>



Hmm… stosuj Boxy zamiast tabel, a dobrze na tym wyjdziesz
. Zarowno semantycznie jak i wygodowo. Wiem, bo sam sie przekonałem (choć to było w Pythonie a nie PHP).
Hmm w jakim sensie semantycznie? :>
Hmm.. no można porównać tabelki z GTK do tabelek w HTML, oraz analogicznie boxy do divów, rozumiesz
? Kiedyś czytałem na ten temat artykuł, ale nie mam pojęcia gdzie.
Taka tabelka jaką przedstawiłem, raczej jest trudna do porównania do tej z HTMLa
Zamiast tej tabeli, co w nią wrzuciłeś labels i entries dajesz boxy.
GTK jest ostro popieprzone jesli chodzi o ukladanie elementow. Probowalem juz kiedys zrobic jakas aplikacje, i sie poddalem. Innym razem
Shoes w Ruby on Rails rlz, serio. Rzuć to PHP-GTL ;-D
W GTK podoba mi się właśnie pomysł układania elementów w tabelki – ideologicznie poprawne
.
W Windows wszystko ustawia się co do piksela i jest to moim zdaniem niewygodne…
Probowałeś zrobić kiedyś całość na boxach zamiast tabelek?
VBox/HBox masz na myśli?
Exactly.
Używałem
. Czasami nawet musiałem użyć tabelki, a w niej *Boksa :] .