Първи стъпки в PHP-GTK
В тази статия ще ви запознаеме с PHP-GTK и писането на десктоп приложения с PHP.
Какво е PHP-GTK?
Това е РНР разширение, което ни дава възможност да пишем приложения от страна на клиента, т.нар. десктоп приложения (няма нищо общо с аплетите – бел.ред.). За да се стартира това приложение не е нужно на компютъра да има Apache, PHP. На адрес http://gtk.php.net можете äа намерите повече информация както и необходимия ви инсталационен пакет.
Инсталиране на Windows
В последния пакет се съдържат:
o ./php4 -> РНР и GTK файловете
o ./winnt -> съдържа файлът php.ini
o ./test -> примери
o README
Създавате папка php-gtk(примерно в D:php-gtk), след което копирате съдържанието на папката php4(виж по-горе) в тази папка. На същото това място копирате и файлът php.ini от папка winnt. За да може вашето приложение да показва текст на кирилица намерете php-gtk.codepage в php.ini и му задайте стойност CP1251.
PHP-GTK предоставя две възможности за стартиране на приложенията ви – с конзола и без конзола. При първия вариант PHP стартира конзола, където се извеждат съобщенията за предупреждения и грешки. Вторият начин (чрез php_win.exe) PHP не показва конзолен прозорец, като така подтиска всички съобщения за грешки, без които приложението може да стартира. В случай на фатална грешка, обаче вие не можете да видите каква е тя точно, поради което този начин е по-удобен за финализираните приложения.
За по лесно тестване на приложенията измислете си разширение различно от .php( примерно .pgtk), след което от File Type създайте нов тип файл и му задайте да се отваря с помощ на php_win.exe(файлът се намира в папката където сте инсталирали PHP-GTK-то).
Hello World.pgtk
<?php dl("php_gtk.".(strstr(PHP_OS, "WIN") ? "dll" : "so")); $window = &new GtkWindow(); $window->set_position(GTK_WIN_POS_CENTER); $window->set_title("Test"); $window->set_default_size(120, 20); $window->set_border_width(5); $window->connect_object("destroy", array("gtk", "main_quit")); $button = &new GtkButton('Hello World'); $button ->connect_object("clicked", array("gtk", "main_quit")); $window->add($button); $window->show_all(); Gtk::main(); ?>
За да правим каквато и да е програма първо трябва да заредим нужния ни файл(php_gtk.dll за Windows или php_gtk.so за Linux дистрибуциите). С първия ред от програмата показана по-горе правим точно това, ако ОС ни е Windows зареждаме dll файла,а ако не - so файла. След което създаваме прозорец с размери 120х20, със заглавие ”Test”, с дебелина на бордера 5 пиксела, който винаги ще се показва на средата на екрана ни. В този прозорец ще имам бутон с надпис „Hello World”, който при натискане ще затваря прозореца.
$window->add($button); - с този ред добавяме $button към прозореца. Ако не го направим бутона няма да се покажа.
$window->show_all(); - показва цялото съдържание на прозореца $window, който създадохме.
Gtk::main(); - GTK извиква функцията main() и нашата програма се стартира като е готова за получаване на различни сигнали(в този пример това е сигналът за затваряне).
Първа програма.pgtk
Това е програма, която търси данни в един файл по зададени параметри. Параметрите ги въвежда потребителя на програмата, като първото е число отговарящо на цолове, а второто размер на гумата, при което програмата показва освен тези данни и другите два размера. Програмата ще има меню – File[ Search | Quit ], Option [ Others | Theme] и Help[ About ], както и форма в която да въвеждаме данни чрез, които да се извършва търсенето

Фиг.1
Като за начало трябва да заредим „нужните продукти”:
dl(”php_gtk.”.(strstr(PHP_OS, “WIN”) ? “dll” : “so”));
След като сме си заредили нужния файл вече можем да създадем „прозореца” на нашето приложение това става като създадем нов обект от класът GtkWindow().
|
$window = &new GtkWindow(); |
Създаваме нов обект; |
|
$window->set_position(GTK_WIN_POS_CENTER); |
Този метод указва на „прозореца’ да се визуализира в средата на екрана; |
|
$window->set_title(”НАИМЕНОВАНИЕ”); |
Задаваме заглавие на прозореца; |
|
$window->set_default_size(300, 100); |
С помощта на този метод задаваме големината на прозореца; |
|
$window->set_border_width(0); |
Задаваме дебели на рамката; |
Вече създадохме „прозореца” нека да добавим една вертикална кутия, в горната част на която ще разположим менюто, а в долната формата за търсене(както се вижда на фиг.1).
$vbox = &new GtkVBox();
$window->add($vbox);
#menu
$menugroup = &new GtkAccelGroup();
$window->add_accel_group($menugroup);
$Item = &new GtkItemFactory(GtkMenuBar::get_type(), “<mainmenu>”, $menugroup);
$menuItems = array(
array( “/_File/_Search”, “<CTRL>S”, “menucall”, 1, “” ),
array( “/_File/sep”, null, null, 0, “<Separator>” ),
array( “/_File/_Quit”, “<CTRL>Q”, “menucall”, 100, null ),
array( “/_Option/_Others”, “<CTRL>X”, “menucall”, 1, “” ),
array( “/_Help/_About”, “F1″, “menucall”, 2, “”)
);
$Item->create_items($menuItems);
$vbox->pack_start($Item->get_widget(”<mainmenu>”), null, null, 0);
…
Както се вижда от кода правим една “accel” група $menugroup, която добавяме към $window. Ако погледнете php_gtk ръководството-а ще видите, че има и други начини за създаване на меню, но на мен този ми се стори най-ефективен и най-лесен. Масива $menuItems съдържа елементи, които характеризират менютата от нашата програма. Всеки елемент е масив със следните елементи:
1) Име на меню и под меню.
2) Комбинацията от клавиши за бърз достъп
3) Функцята която се извиква при даден избор
4) Параметър на функцията от 3)
5) Тип елемент(прост[както в този пример], check, radio …)
С помощта на метода create_items преобразуваме масива в меню. А с послеäния ред от кода по-горе добавяме менюто в горната част на вертикалния контейнер. Но нека да добавим и списъка от темите, от които потребителя може да избира
$moreItems = array();
$dir = “./themes”;
if (is_dir($dir)) {
$opendir = opendir($dir);
$i = 0;
while (($file = readdir($opendir)) !== false) {
if ( (is_dir($dir.”/”.$file)) && (strpos($file, ‘.’) !== 0) ) {
if ($i < 1) {
$m = “/Option/Theme/”.$file;
$moreItems[$i] = array(”/_Option/_Theme/”.$file, null, “theme”, ($i * 10), “<RadioItem>”);
}
else {
$moreItems[$i] = array(”/_Option/_Theme/”.$file, null, “theme”, ($i * 10), $m);
}
$i++;
}
}
}
closedir($opendir);
$Item->create_items($moreItems);
$dtheme = $Item->get_widget( “/Option/Theme/”.theme(1) );
$dtheme->set_active(true);
Отваряме директорията с темите и взимаме имената на всички папки(визуални теми) като ги добавяме като радио бутони към подменюто Theme. При избор на някоя от темите се извиква функцията theme(), която ще разгледаме по късно.
Сега иäва ред на голямото писане – частта за създаване на формата, която е съставена от 2 полета, в които да може да се пише както и един бутон, който да изпълни действието: търсене. Като за начало създаваме контейнер( &new GtkHBox), но този път хоризонтален, в който ще слагаме всичките елементи от формата. GtkLabel(“текст”) е етикет, който „отпечатва” текста намиращ се на мястото на „текст”. Етикета го използваме да подскажем на потребителя, че от него се очаква да „Въведе стойност”, а най отдолу го използваме да изпишем, че това е версия 1.01 на програмата. Методът set_alignment(x.x, y.y) ще използваме за да позиционираме етикета, като x.x е разстоянието от левият ръб, а y.y от десния ръб на контейнера.
$danni = &new GtkHBox();
$label = new GTKLabel(” Въвеäете стойност:”);
$label->set_alignment(0, -1);
$danni->pack_start($label);
Създаването на текстово поле става с GtkEntry(), като с помощта а метода set_uposition(Х, У) задава ме абсолютни координати по Х и У спрямо левия горен ъгъл на приложението.
$ctext = &new GtkEntry();
$ctext->set_usize(22, 20);
$ctext->set_uposition(10, 54);
$ttc = &new GtkTooltips();
$ttc->set_delay(100);
$ttc->set_tip($ctext, “öолаж”);
$ttc->enable();
$danni->pack_start($ctext);
За да подскажем на потребителя нещо повече за това поле можем да използваме tooltips. Както виждате в кода по-горе ние създаваме един обект от класа GtkTooltips(), задаваме му текста, който искаме да покажа с метода: set_tip(елемент, текст), закъснението с което да се показва с set_delay(time) в милисекунди и накрая го разрешаваме с enable();. По същия начин правим и другото поле, което в тази програма ще е за размера на гумите. Ето и как да създадем бутон, който да вземе въведените стойности и да ги изпрати на подходящото място:
$ok = &new GtkButton(”провери”);
$ok->set_usize(60, 20);
$ok->set_uposition(110, 54);
$ok->connect_object(”clicked”, “search”, $ctext, $stext);
$ttok = &new GtkTooltips();
$ttok->set_delay(100);
$ttok->set_tip($ok, “изпълни”);
$ttok->enable();
$danni->pack_start($ok);
Създаваме бутон с име провери и tooltips изпълни, с координати 110 и 54, а с помощта на метода set_usize (w, h) задаваме размера на бутона: широчина и височина. Предаването на данни става с метода connect_object(“тип”, „име на функция”, „параметър 1”, „параметър …’); като типовете са: clicked, pressed, destroy. На практика този метод “закача” зададената функция на определено събитие от обекта (в нашия случай това е clicked). В случая ние подаваме на функция search обектите $ctext и $stext.
Функцията за търсене представлява най-обикновенна фукнция на php, която отваря файла с данните, проверява за съвпадения и показва резултата в един прозорец в един етикет(GtkLabel). Нека да обърнем внимание на една особеност в нея и това е, че „преобразуваме” подадените обекти в стойност. С помощта на метода get_chars(0, -1) взимаме стойностите от полетата, в които потребителя въвежда данни, ако не въведе нищо програмта се изключва сама, но би било добре äа се сложи една проверка. Тази част от приложението ще го оставим за ваша самостоятелна работа.
function search($width, $second) {
$width = $width->get_chars(0, -1);
$second = $second->get_chars(0, -1);
$data = @file(”./data.txt”);
for ($i = 0; $i < count($data); $i++ ) {
$field = @explode(”;”, $data[$i]);
if ( ereg($width, $field[0]) and ereg( strtoupper($second), $field[1]) ) {
$result .= “Öолове: “.$field[0].”” широчина: “.$field[1].”nразмер II: “.$field[2].” размер I: “.trim($field[3]).”nn”;
}
}
if ( empty($result)) {
$result = “Няма намерени äаниn”;
}
//end search ver 1.0
$swin = &new GtkWindow();
$swin->set_position(GTK_WIN_POS_CENTER);
$swin->set_title(”Резултат”);
$swin->set_default_size(200, 60);
$swin->set_border_width(0);
$swin->connect_object(”destroy”, array($swin, “destroy”));
$box = &new GtkVBox();
$label = &new GtkLabel(”n”.$result);
$box->pack_start($label, false);
$close = &new GtkButton(”затвори”);
$close->connect_object(”clicked”, array($swin, “destroy”));
$box->pack_end($close, false);
clear();
$swin->add($box);
$swin->show_all();
}
В кода на функцията search се извиква една друга функция clear(), тя задава стойност „” на двете текстови полета на формата за търсене.
function clear() {
global $ctext, $stext;
$ctext->set_text(”");
$stext->set_text(”");
}
До тук програмта работи показва резултатите, които искаме, но менюто е само един текст нека да направим и него функциониращо. Функцията menucall() приема един параметър $number с помоща на който определяме кой бутон от менюто е избран и какво действие да извърши програмта ни.
function menucall($number) {
switch($number) {
case 1:
clear();
break;
case 2:
about();
break;
case 3:
choose();
break;
default:
gtk::main_quit();
break;
}
}
При F1 обикновенно се извиква help файла на програмта, но просто за тази програма не виждам какъв help би могло да има J затова при натискане на F1 извикваме функдията menucall(2), което от своя страна изивка функдията about(). При създаване на „прозореца”, в който ще покажем някаква информация за програмата има една особеност
$awin = &new GtkWindow(GTK_WINDOW_POPUP);
Указваме на прозореца, че няма да е тип TOPLEVEL, както е в другите прозорци, които сме създали досега, а ще е от тип: popup(виж фиг.2). В него се съдържа едно тестово поле и един бутон за затваряне. GtkText() създава поле с което можем да покажем данни от програмта или ако разрешим потребителя да пише в него.

Фиг.2
В случая ние искаме да покажем текст без да даваме възможност на потребителя на програмта да добавя или да променя това.
$text = &new GtkText();
$string = “(c) PureEvilnn 5.5.2005nnGNU LGPL”;
$text->insert_text($string, 0);
Няколко екстри
Стилът на прозореца
Тези от вас, които са видяли примерите, които се разпостраняват с пакета PHP-GTK или са писали някакво приложения са забелязали, че не се ползва стила по-подразбирене. GTK::rc_parse(„…”) с тази функция зарежда файл, в който описваме стилът на приложението( цвят на текст, на фон …).
#module_path “./engines” #not use
style “default”
{
fg[NORMAL] = “#000000″ #text
fg[ACTIVE] = “#000000″ #onmouse click
fg[PRELIGHT] = “#FF0000″ #onmouse over
bg[NORMAL] = “#D3D3DD” #main bgcolor
bg[ACTIVE] = “#C1C1CC” #button bgcolor onmause click
bg[PRELIGHT] = “#E5E5F7″ #button bgcolor onmause over
base[NORMAL] = “#E5E5F7″ #bgcolor form
#load font
font = “-*-helvetica-medium-r-normal–*-126-*-*-*-*-*-*”
}
class “GtkWidget” style “default”
Тъй като в програмата е превидено да могат а се ползват много теми трябва да имам една функция theme($level), с чиято помощ избираме или променяме стълът.
function theme($level) {
global $moreItems;
if ($level != 1) {
$ind = $level / 10;
$level = substr($moreItems[$ind][0], 16);
$fn = @fopen(”./themes/theme.ini”, “w”);
@fwrite($fn, $level);
@fclose($fn);
}
else {
$tname = @file(”./themes/theme.ini”);
return trim($tname[0]);
}
}
При стойност на $level == 1 функцията връща стринг с пътя до избраната от нас тема, която се зарежда с помощта на GTK::rc_parse(”./themes/”.theme(1).”/gtkrc”);. В противен случай отваряме файла theme.ini за писане и записваме името на избраната от нас тема, която избиреме от менюто.
Повече за темите можете да намерите на http://gtk.themes.org
Компилиране на сорс кода до изпълним файл(.exe) + още нещо
Тук ще ви покажем съвсем накратно как да се създаде изпълним файл от вашия скрипт.
За тази цел ще ни е нужна програмта PriadoBlender, която можете да намерите на http://www.priadoblender.com/. След като инсталирате програмата направете си една папка „FIRSTPGTK” и стартирайте PriadoBlender(фиг.3).
- File To be Compiled – от тук си избирате файла, който сте писал
- Output File Name – задавате име на файла, който ще се компилира не забравайте да му напишете и разширението( .exe), защото програмата не го добавя автоматично.
- Output Directory – избирате папката, която направихте преди малко
- След това избирате Pull In Includes, а Usage GTK го оставяте както си е
- Натискате Compile и след няколко секунди имате програмта.
Сигурно сте забелазяли, че програмта става доста голяма, а всъщност не прави почти нищо. Това е така заради ненужните екстри(поне сигурно така си мислят създателите на програмата), които се намират в Output папката.

Фиг.3
Ето и няколко съвета как да дообработите компилиранта програма:
- Изтрийте папките themes и lib в тях се съдържат примерни gtk теми, php-gtk програми, които ви казват как да позлвате темите, но ако пуснете програмта на компютър без инсталирано GTK просто няма да видите никаква заредена тема J. В папката lib са разположени php-gtk.extensions, които в този пример не са ни нужни, така че можете äа ги коментирате този реä в php.ini
- Папката bin не е празна вътре има един exe файл, който ви е нужен да работи програмта – не го изтривайте(той е hidden)
- Както вижäате има много dll файлове, в зависимост от това какво ползвате в програмта си можете да изтриете част от тях. Ако не можете да се ориентирате по името на файла просто изтрийте един файл стартирайте програмта ако тръгне и всичко е работи значи не ви трябва J
- Копирайте файловете data.txt, папките engines и themes. Тъй като още в началото сме редактирали темите да търсят на тези места нужните им файлове. Все пак програмта трябва да работи и на компютър на който няма GTK нали?
- Ако в програмта позлвате кирилица отворете php.ini и добавете следния ред php-gtk.codepage = CP1251
Ето че програмта от 11MB стана 6MB, все пак не се ползват повечето възможности на PHP-GTK и затова повечето разширения не са ни нужни.
За финал
В тази статия не са разгледани всички методи, които притежават класовете изпозлвани тук (GtkWindow, GtkText и т.н.), така че набавете си manual файла(или файлове) от http://gtk.php.net.
Въпроси можете да задавате във форума на http://php-bg.org или да търсите отговорите с http://google.com.
От адрес http://pure.none-corp.org/download/search[php-gtk].rar можете да свалите сорс кода на програмта разгледана в тази статия, файл с данни в който да се търси, 4 теми както и нужните за тях engines(големината му е 170KB).











