首页 > 开发 > PHP > 正文

PHP-GTK 介绍及其应用

2024-05-04 22:54:18
字体:
来源:转载
供稿:网友
1. php-gtk介绍

1.1 php-gtk
php-gtk是php的延伸模组,它可以让程式设计师写出在客户端执行的、且独立的gui的程式。这个模组不允许在浏览器上显视gtk+的程式,它一开始就是开发来写独立的gui程式的。

1.2 gtk
gtk原本是为gimp,一个gui的影像处理软体而开发的。gtk+是gimp的套装工具。gtk+从这里开始发展,直到现在已经成为gnome的中心(gnome是一个桌面环境)。後来gtk+也已经被推广到beos和win32,使得它成为php延伸模组的最佳选择,维持php可以跨平台并可以用php为linux,beos,windows等平台开发视窗介面的程式。

2. php-gtk概念

2.1 前言
接下来就要教各位一点点比较观念性的东西罗┅因为这章的概念都是非常重要的,所以就算不懂,也还是要慢慢的看懂它,不然┅以後就┅。还有,接下来的内容不建议没有程式设计经验的读者阅读,因为有很多的观念很容易会搞不清楚。还有,接下来该用英文的部分我都会用英文,这样大家在看国外文件的时候才不会不知所措,加油吧!!如果对本章有任何不懂之处,请自行查阅
php-gtk manual:http://gtk.php.net/manual/en/

2.2 widget(s)
widget是一个gui程式中基本的functions和forms。最常用的几个widget是:label、button、window、frame和text box。所有的widget都是来自於一个抽象的基本class─gtkwidget。每个widget都是一个class

一个widget一生大概都有五个时期:
1. 建立(creation):宣告一个物件(declaring an object)
2. 放置(placement):将它加入一个容器中(adding it to a container)
3. 信号连接(signal connection):接收信号以及进行动作(the action it will perform)
4. 显示(display):它是否是可见的(whether it is viewable or not)
5. 删除(destruction):关闭程式(closing of a program)

2.3 container(s)
container是一个可以包含其他widget的widget。大部分的widget都是container,例如:gtkwindow、gtktable和gtkbox。除了这点之外,container跟其他的widget没两样,也可以被放到其他container去。而所有的container都是来自於一个class─gtkcontainer,本身来自於gtkwidget的class。所以container也是widget的一种。

2.4 signal(s)
当程式设计师在程式中做了一个动作时,程式需要有一个动作来回应使用者的动作。signals使程式可以知道使用者做了动作并可以触发适合的回应。

例如,当使用者按了一个可以开新视窗的按钮(gtkbutton),程式认出这个请求,於是就开了一个新的视窗。这件事可以经由signal来做到。当按钮按下去之後,会使widget发出一个signal,接着再由该signal触发callbacks,产生一个新的视窗(gtkwindow)。

2.5 callback(s)
callback就是当signal送出之後,被signal唤起的function。callback会执行function传回一个值或是做一个动作。callback就是signal的handler funciton。它可以是该signal的预设handler或着是程式设计师定义的function。要建立一个callback,就必须把function connect 到 signal。

2.6 signal inheritance(继承)
和methods一样,signals可以被物件继承。一个widget可以送出任何它的parent widget可以送出的还有它自己特有的signal。

2.7 connecting signals
你必须为php-gtk指定一个callback function当signal送出时来对signal做回应。把一个signal连接到一个function可以用connect() 这个object 方法达成。

如下:

<?php
//建立一个gtkwindow
$window = &new gtkwindow();
//将"destroy" signal用connect() 方法连接到shutdown函式
$window->connect("destroy", "shutdown");
//建立一个gtkbutton,按钮文字为"按我"
$button = &new gtkbutton("按我");
$button->connect("clicked", "you_clicked");
//把gtkbutton放到是container的gtkwindow中
$window->add($button);
//显示$window以及它的所有child widget
$window->show_all();
//进入程式主回圈(即程式启动之意)
gtk::main();
?>


执行它的话,就会出现一个视窗,里面有一个写着"按我"的按钮,按下按钮程式就会执行you_clicked函式。在这个程式中,$window物件的"destroy" signal是在使用者按下视窗右上角的"x"时会送出的;而$button物件的"clicked" signal是在使用者按下该按钮的时候会送出的。最後那一行的gtk::main() 是一定要执行的,这样才能告诉电脑要开始执行程式,既然有开始执行,那就一定有停止吧? 没错,用gtk::main_quit() 就可以停止程式了。

看完了以上的范例,有些读者可能会有疑问「如果我想执行送出signal的widget之外的widget的method怎么办?」,这时候,就要用另一个method了 a connect_object(),它可以跨物件呼叫方法或是传递其他物件做为function的叁数。跨物件呼叫方法如下:

$window->connect_object("destroy", array("gtk","main_quit"))


如此,在$window物件的"destroy" signal送出的时候就会唤起gtk::main_quit()这个方法,程式就会终指执行。

在介绍连接方法的最後,再提一下connect() 和 connect_object() 的自订增加要传给callback function的叁数的办法。见例子:
<?php
$parameter="新超人";
$button1 = &new gtkbutton("测试");
//将"clicked" signal连接到who_are_you函式,附加叁数$parameter
$button1->connect("clicked","who_are_you",$parameter);
$button2 = &new gtkbutton("测试二");
//将"clicked" signal连接到kill_the_button1函式,附加叁数$button1
$button2->connect_object("clicked","kill_the_button1",$button1);

function who_are_you($widget,$parameter){
echo $parameter;
}

function kill_the_button($button){
$button->destroy();
}
?>


注意那两个function,who_are_you有两个叁数对吧? 第一个是做什么用的呢?为什么它会自动出现?? 因为,每个signal的callback function都会因为signal的不同而加上一些内定一定会传入callback function的叁数,而基本上所有的signal都至少会传给callback function一个叁数a产生该signal的物件。所以who_are_you的第一个叁数就是$button1,而第二个就是$parameter,也就是新超人。那kill_the_button函式就不一样罗~ 因为connect_object()函式会呼略原本signal的callback function的预设叁数,所以kill_the_button就只有附加在connect_object最後的$button1叁数了,如此,kill_the_button就可以呼叫$button1的方法或是取得它的属性,这里呼叫了$button1的destroy方法,於是$button1就会被消灭。

2.8 event(s)
event是signal的一种,但是它的用途还有功能都非常强大。就signal来说,signal这种东西都是内建在widget上的,所以,例如gtkwindow没有"clicked"signal,那么在不用event signal的情况下,gtkwindow是决对不可能送出clicked之类的signal的。那如果用了event signal呢? event signal是可以允许被加到任何的widget上的,所以就算这个widget本来没有发出"clicked"signal的功能,你也可以用add_events() 来为它加上按了它之後event signal会做什么样的反应。而event signal中包含的资讯比较多,比如说当你在使用"key-press-event"这个event signal的时候,同时也会记录到你按下的是什么按键,於是通常event signal的callback function格式内定会有两个叁数,第一个依然是送出signal的widget,而第二个就是$event,这个$event是一个class,里面的属性和方法会因为送过来的event signal种类而不同。就"key-press-event"传回的$event class来说,里面有一个属性是keyval,内容就是使用者按的是哪一个键。这些对於一个程式设计师来说常常是很有用的资讯。所以event的重要性是不可忽视的,就算刚开始会有点不懂,也要慢慢的融入才行。这一节也非常重要。

3. 安装php-gtk

3.1 在windows系统下安装
首先要从http://gtk.php.net/download.php下载...hp-gtk的windows binary档案(本文撰写时为0.5.1版)。

接着来看看php-gtk 0.5.1 binary档的内容:
php4 → php 和 php-gtk binary 档案
winnt → 预设的php.ini档案
winntsystem32 → gtk binaries used by extension
test → 几个测试用的档案
readme.txt → 安装说明档

开始安装:
1. 复制 php4 的内容到你的php安装目录下(例c:php)。
2. 复制 winnt 的内容到你的winnt资料夹。在windows nt或windows2000上是c:winnt,在window95、98、xp上是c:windows。如果该资料夹里已经有 php.ini,那就不用做这个动作。
3. 复制 winntsystem32 的内容到你的winntsystem32资料夹。在windows nt或windows2000上是c:winntsystem32,在window95、98、xp上是c:windowssystem32。
4. 复制 test 的内容到你想要执行你的script的地方(此步骤非必要)。

如何执行php-gtk程式:
php-gtk程式可以在「开始」-「执行」下输入指令(或是建立捷径)来启动,如:c:phpphp -q c:phptestgtk.php ## 表示不送印出 http header,但一直使用这个视窗,直到关闭程式。
c:phpphp -q -c php.ini c:gtk.php ## 同上,但执行指定的php.ini设定。
c:phpphp c:phptestgtk.php ## 表示会送印出 http header,但一直使
用这个视窗,直到关闭程序
c:phpphp_win c:phptestgtk.php ## 表示不使用视窗,执行後独立一个执行程式,他是使用 php -q模式,但是只要output出任何字元,例如错误讯息,就会停止执行。

3.2 在unix系统下安装
debian的使用者可以在 http://www.debian.org 下载php-gtk的binary档。系统需求须已安装下列package:

php 4.1.0 或之後的版本,必须是编为cgi binary(command-line) 版本,包含所有的header files和devlement scripts。

php-gtk支援gtk+ v1.2而需要安装1.2.6以上版本的gtk+。gtk+ v2.0还未被支援,必须等到它开发完成并且普及了之後才会被支援。你可以从下面的网址取得gtk+ v1.2.x的最新版本:ftp://ftp.gtk.org/pub/gtk/v1.2/

在将取得的档案解压缩或是由cvs中check out出来之後,切换到该目录下,开始进行安装(打指令罗~):

取得cvs版本,执行
cvs -d server:[email protected]:/repository co php-gtk
或下载最新版本
http://gtk.php.net/download.php

1. ./buildconf
2. ./configure (想要加装extensions的话请输任./configure --help看说明)
3. make(如果看到"could not write┅",只是代表该gtk+ object还没被支援,不算是什么错误讯息)
4. make install

执行看看test/资料夹中的范例scripts来测试,特别是gtk.php,这些都是展示如何使用的好例子。

4. 第一支程式

4.1 前言
本章会教导各位一些常用的gtkclass(widget),还有运用这些来做出你的第一支php-gtk程式,如果概念那章不是很熟的话,这章可以给你一个练习的机会喔! 如果对本章的内容有不懂或是想要深入了解其他的widget,可以到http://gtk.php.net/manual/en/ 看手册,手册里面有不少范例程式。

4.2 会用到的widgets
在开始写程式之前,先来对等一下会用到的widget class们做一个overview。

gtkwindow()
gtkwindow()建立一个视窗,里面有很多方法可以使用,如:set_title,set_name,
connect,set_border_width等┅。

gtkframe()
gtkframe()纯粹建立一个好border,你可以设定它的label name,alignment,
shadow(用英文,读manual的时候会比较方便)。

gtkvbox()
gtkvbox()建立一个直立的container来放入widgets。

gtklabel()
gtklabel()可以建立一个label,内容文字可以建立时设定也可以建立後用方法来设定,如果没有设定内容文字,将会建立一个空的label(这是废话吗┅?)。

gtkhseparator()
gtkhseparator()建立一个水平线。

gtkentry()
gtkentry()建立一个textbox供使用者输入资讯。

gtkhbuttonbox()
gtkhbuttonbox()建立一个以水平方式排列button的container。

gktbtton()
gtkbutton()或许可以说是gui程式中最常用的widget了,它建立一个可以让使用者按的按钮。

4.3 开始

if(!class_exist("gtk"))
{
dl("php_gtk.".(strstr(php_os,"win") ? "dll" : "so"));
}


这段程式码会判断php-gtk延伸模组是否已启动,如果没有,它就会读取适当的档案。在上面的范例中,是靠判断执行的作业系统是windows还是其它来判断要载入php_gtk.dll还是php_gtk.so。


function delete_event()
{
return false;
}


这里建立了一个名为delete_event的function,这个function是等会儿delete-event signal发出时的callback function。内容传回false会告诉php-gtk用预设的signal handler来处理,而预设的handler会关闭视窗(同时会呼叫该视窗的destroy() 函式),在这里,它会关闭程式(因为这个范例程式只有一个主视窗,一旦关闭就会关闭程式)。

function destroy()
{
gtk::main_quit();
}


这里建立了一个函式,destroy()。在这个程式中,这个函式是很重要的,因为我们在关闭程式的时候会连接到它。之前说过,gtk::main_quit()会关闭程式,如果我们在这个程式中没有定义这个function或是这个function里面没有gtk::main_quit()这行,那么这个程式就不会关闭了。以上一段程式码说明里提到的delete-event来说,return false之後预设会执行关闭视窗的动作,还会呼叫destroy()函式,如果这里没有定义或是没有gtk::main_quit()这段的话,主视窗的确会关闭,可是程式并不会结束,因为主程式回圈agtk::main()还在跑。

<?php
$window = &new gtkwindow();
//设定名字以辨别各个视窗
$window->set_name('main window');
//设定视窗的标题
$window->set_title('对php-gtk的介绍');
//设定视窗的大小
$window->set_usize(160, 120);
//呼叫destroy()函式来结束程式
$window->connect('destroy', 'destroy');
//呼叫delete_event()函式来关闭视窗
$window->connect('delete-event', 'delete_event');
//设定视窗的边框宽度
$window->set_border_width(10);
//设定视窗的位置
$window->set_position(gtk_win_pos_center);
//显示视窗和所有child widget (不显示就看不到)
//最後这两行一定要放在程式码的最後,否则什么都看不到
$window->show_all();
gtk::main();
?>


执行程式可以看到如下的图:





//建立一个gtkframe
$frame = &new gtkframe('经过简易修改的程式');
//把gtkframe放到gtkwindow里
$window->add($frame);
//最下面两行不要动


结果如下图:





下面这段建立一个gtkvbox作为container,并把gtkentry、gtkhseperator、gtklabel和gtkbuttonbox都pack进去,所谓pack,是gtkbox底下的container们特别加入的放入widget的方法,就类似於add(),而pack用的方法一般是pack_start()和pack_end(),比add()好的地方是可以控制将widget增加进去之後widget的位置(不过只要是container就会有add()方法),欲查询详细资料请至
http://gtk.php.net/manual/en。


//建立一个gtkvbox,为常用的container
$box1 = &new gtkvbox();
//把gtkvbox放到gtkframe里面
$frame->add($box1);
//建立一个gtklabel并将它pack到gtkvbox里
$label = &new gtklabel();
$box1->pack_start($label);
//建立一个gtkhseparator并将它pack到gtkvbox里
$separator = &new gtkhseparator();
$box1->pack_start($separator);
//建立一个gtkentry并将它pack到gtkvbox里
$entry = &new gtkentry();
$box1->pack_start($entry);
//建立一个gtkbuttonbox并将它add到gtkvbox里
//因为gtkbuttonbox也是一个无形的container,位置不重要,所以用add()
$box2 = &new gtkhbuttonbox();
$box1->add($box2);



执行如下图:





最後这段程式码会建立两个gtkbutton并pack到gtkbuttonbox里去,还有为两个按钮加上连接,使它们起作用,并建立一个函式,只要按下gtkbutton就会将gtklabel的内容换成gtkentry中的文字。

$button = &new gtkbutton('显示输入的字');
//连接"clicked" signal到set_name()函式,附加$label和$entry两个widget
$button->connect_object('clicked','set_name',$label,$entry);
$box2->pack_start($button);
$button = &new gtkbutton('离开程式');
//连接"clicked" signal到destroy()函式,将会关闭程式
$button->connect('clicked','destroy');
$box2->pack_start($button);

function set_name($label,$entry)
{
//用gtkentry的get_text()方法从取得文字方块内容
$gettext=$entry->get_text();
//用gtklabel的set_text()方法设定新的文字
$label->set_text($gettext);
}
//最後再提一下那两行┅.
$window->show_all();
gtk::main();


寫到這裡,整個程式就算是完成了,來看看執行的結果吧~






5. 其它

5.1 进一步学习
如果在结束了上面的课程之后你还想要更了解php-gtk,或是对于本文的内容有任何
不明白的地方,这里提供你几个地方可以查询资料:

php-gtk官方网站(en): http://gtk.php.net
gtk官方网站(en): http://www.gtk.org
php-gtk官方网站上的manual(en): http://gtk.php.net/manual/en
tim官方网站(zh-tw): http://tim.jerry.com.tw

5.2 另一个范例
这里有一个笔者写的猜数字游戏,算是比较进阶的范例,可以抓回去研究看看。
http://pc035860.infor.org/download/guessnumber.zip

5.3 参考数据
本文主要是参考php-gtk官方manual和zend网站上的tutorial而编撰成的:
http://gtk.php.net/manual/en
http://www.zend.com/zend/tut/tutorial-silva.php
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表