Forum und email

Здравей свят (за напреднали)

В този урок ще задълбочим разгледания в предишният урок пример Здравей Свят. Ще създадем прозоре, в който потребителя трябва да въведе потребителското си име и парола за достъп. Когато потребителя натисне бутона Вход, текстовите полета ще бъдат проверени и ще бъде отпечатена грешка ако не са въведени правилно потребителското име и парола за достъп.

Ето така ще изглежда програмата, когато бъде завършена:

Първото нещо, което трябва да направим е, да създадем прозорец, да му зададем заглавие и да кажем на главният цикъл да прекъсне програмата, ако прозореца бъде затворен. Това вече знаете от първият урок:

$wnd = new GtkWindow();
$wnd->set_title('Login');
$wnd->connect_simple('destroy', array('gtk', 'main_quit'));

Следващата стъпка е създаването на всички уйджети за този диалог: създаваме две текстови полета за въвеждане на потребителско име и парола за достъп:

$txtUsername = new GtkEntry();
$txtPassword = new GtkEntry();

Необходимо е да създадем описателни етикети, за да може потребителя да знае къде да въведе потребителското име и къде паролата за достъп:

//The second parameter says that the underscore should be parsed as underline
$lblUsername = new GtkLabel('_Username', true);
$lblPassword = new GtkLabel('_Password', true);

За край ни трябват и два бутона - единият за вход, другият за отказване:

$btnLogin    = new GtkButton('_Login');
$btnCancel   = new GtkButton('_Cancel');

Може би забелязвате, че конструктура GtkLabel приема втори параметър - долна черта _, за да може първата буква да се изобрази като подчертана. Както забелязвате същото нещо не се прави с конструктуро на бутона, тъй като той го прави автоматично. Това поведение може би ще Ви се стори странно, но ще Ви помогне при разграничаване на етикетите на бутоните от самите етикети.

Сега трябва да покажем на етикетите кой уйджет да активират при избиране на подчертаната буква. Това се прави по този начин:

$lblUsername->set_mnemonic_widget($txtUsername);
$lblPassword->set_mnemonic_widget($txtPassword);

Следващата процудура е да определим какво действие ще се извърши, когато е натиснат даден бутон. Бутонът за изход (Cancel) ще разруши прозореца, т.е. ще прекрати нашата програма, а бутонаът за вход Login ще провери техтовите полета и ще продължи с други действия:

$btnCancel->connect_simple('clicked', array($wnd, 'destroy'));
$btnLogin ->connect_simple('clicked', 'login', $wnd, $txtUsername, $txtPassword);

Предаваме три уйджета като допълнителни параметри към функцията за вход, която още не е дефинирана, (login function) - $wnd, $txtUsername и $txtPassword. Тези три уйджета са необходими, за да получим стойностите на текстовите полета и ако всичко е наред да разрушим прозорецът.

Сега след като имаме всичко, трябва да ги добавим в прозорец. Тъй като GtkWindow е бинсарен контейнер, той може да приеме само един уйджет, затова ни трябва друг контейнер, в който да разположим нашите уйджети. Използваме GtkTable, защото ни позволява да запазим етикетите в колони, а стойностите на полетата по следният начин:

$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);

($lblCredit е просто етикет със съобщение). За бутоните използваме GtkHButtonBox, за да можем да разположим няколко от тях:

$bbox = new GtkHButtonBox();
$bbox->set_layout(Gtk::BUTTONBOX_EDGE);
$bbox->add($btnCancel);
$bbox->add($btnLogin);

Слдва да разположим таблицата с бутоните в прозореца. Не е възможно да направим това директно, тъй като GtkWindow е GtkBin и може да съдържа само един уйджет. Затова ни е необходим друг контейнер, който този път е GtkVBox:

$vbox = new GtkVBox();
$vbox->pack_start($tbl);
$vbox->pack_start($bbox);

Това е всичко и сега трябва да покажем прозореца:

$wnd->add($vbox);
$wnd->show_all();
Gtk::main();

Последното, което липсва е функцията за вход login, която се извиква, когато потребителя натисне бутона Вход (Login). Тя трябва да провери стойностите за потребителско име и парола. Ако тяхната дължина е 0, то потребителя не е въвел нищо и ще се появи съобщение за грешка. Ако всичко е наред, прозорецът ще бъде унищожен и програмата ще продължи със зареждане на основният прозорец.

Вземането на техт от уйджет става много лесно с използването на метода get_text() на GtkEntry:

$strUsername = $txtUsername->get_text();
$strPassword = $txtPassword->get_text();

Проверката се прави чрез стандартната функция в php strlen. Ако има грешка ще искаме да покажен кратко съобщение. GtkMessageDialog е идеален, защото автоматически генерира икона и стандартните бутони (Ok, Yes/No):

$dialog = new GtkMessageDialog($wnd, Gtk::DIALOG_MODAL, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, $errors);
$dialog->set_markup("The following errors occured:\r\n<span foreground='red'>" . $errors . "</span>");
$dialog->run();
$dialog->destroy();

Сложете функцията за влизане преди (!) главният цикъл и я стартирайте.

Пример 3.1. Пълният лист на програмата

<?php
/**
*   Here we create a login window.
*   It has a username and a password field, and a
*   Cancel and Login button. Some error checking
*   is being done when the user clicks "Login".
*/

if (!class_exists('gtk')) {
    die("Please load the php-gtk2 module in your php.ini\r\n");
}

/**
*   This function gets called as soon as the user 
*   clicks on the Login button.
*
*   @param GtkWindow $wnd           The login window, needed to close it
*                                    when all is ok
*   @param GtkEntry $txtUsername    The username text field, used to get
*                                    the username
*   @param GtkEntry $txtPassword    The password widget to retrieve the
*                                    password
*/
function login(GtkWindow $wnd, GtkEntry $txtUsername, GtkEntry $txtPassword)
{
    //fetch the values from the widgets into variables
    $strUsername = $txtUsername->get_text();
    $strPassword = $txtPassword->get_text();

    //Do some error checking
    $errors = null;
    if (strlen($strUsername) == 0) {
        $errors .= "Username is missing.\r\n";
    }
    if (strlen($strPassword) == 0) {
        $errors .= "No password given.\r\n";
    }

    if ($errors !== null) {
        //There was at least one error.
        //We show a message box with the errors
        $dialog = new GtkMessageDialog($wnd, Gtk::DIALOG_MODAL,
            Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, $errors);
        $dialog->set_markup(
            "The following errors occured:\r\n"
            . "<span foreground='red'>" . $errors . "</span>"
        );
        $dialog->run();
        $dialog->destroy();
    } else {
        //No error. You would need to hide the dialog now
        //instead of destroying it (because when you destroy it,
        //Gtk::main_quit() gets called) and show the main window
        $wnd->destroy();
    }
}

//Create the login window
$wnd = new GtkWindow();
$wnd->set_title('Login');
//Close the main loop when the window is destroyed
$wnd->connect_simple('destroy', array('gtk', 'main_quit'));


//Set up all the widgets we need
$lblCredit   = new GtkLabel('Please provide your data');
//The second parameter says that the underscore should be parsed as underline
$lblUsername = new GtkLabel('_Username', true);
$lblPassword = new GtkLabel('_Password', true);
$txtUsername = new GtkEntry();
$txtPassword = new GtkEntry();
$btnLogin    = new GtkButton('_Login');
$btnCancel   = new GtkButton('_Cancel');


//Which widget should be activated when the 
// mnemonic (Alt+U or Alt+P) is pressed?
$lblUsername->set_mnemonic_widget($txtUsername);
$lblPassword->set_mnemonic_widget($txtPassword);
//Hide the password
//$txtPassword->set_invisible_char('*');

//Destroy the window when the user clicks Cancel
$btnCancel->connect_simple('clicked', array($wnd, 'destroy'));
//Call the login function when the user clicks on Login
$btnLogin->connect_simple('clicked', 'login', $wnd, $txtUsername, $txtPassword);


//Lay out all the widgets in the table
$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);


//Add the buttons to a button box
$bbox = new GtkHButtonBox();
$bbox->set_layout(Gtk::BUTTONBOX_EDGE);
$bbox->add($btnCancel);
$bbox->add($btnLogin);


//Add the table and the button box to a vbox
$vbox = new GtkVBox();
$vbox->pack_start($tbl);
$vbox->pack_start($bbox);

//Add the vbox to the window
$wnd->add($vbox);
//Show all widgets
$wnd->show_all();
//Start the main loop
Gtk::main();
?>