PyGTK学习笔记

发布时间:2005年03月27日

更新时间:2005年04月21日

Abstract

本笔记基于http://www.pygtk.org上的PyGTK 2.0 Tutorial。


Table of Contents

1. 引言
2. 开始
2.1. 示例
2.2. 信号和回调函数
3. 事件(events)
4. 包装组件

Chapter 1. 引言

PyGTK2.0是Python的一个开发GTK+ 2.X程序的接口模块。通过该模块,我们可使用Python语言开发GTK+程序。相比C语言,开发速度大大提高。PyGTK的主要作者是James Henstridge。可通过这个电子邮件与他沟通:james@daa.com.au。

为了方便学习PyGTK,Johan Dahlin写了一个Python小程序(pygtkconsole.py),它可使我们以python交互环境的形式使用PyGTK。使用该工具,我们可方便地测试PyGTK的功能,而不用编写一个完整的Python程序。下面是一个简单的例子:

debian:~/pygtk# ./pygtkconsole.py
Python 2.3.5, PyGTK 2.4.1 (Gtk+ 2.6.2)
Interactive console to manipulate GTK+ widgets.
>>> w=Window()
>>> w.set_title('window test')
>>> w.show()

这样屏幕上会显示一个标题为“window test”的小窗口。

Chapter 2. 开始

2.1. 示例

我们以一个简单的例子开始本章的内容,这个程序叫base.py,它会创建一个200X200的窗口,但没有设计退出程序,所以只能用shell的中断功能强行结束程序。

    1   #!/usr/bin/env python
    2
    3   # example base.py
    4
    5   import pygtk
    6   pygtk.require('2.0')
    7   import gtk
    8
    9   class Base:
   10       def __init__(self):
   11           self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
   12           self.window.show()
   13
   14       def main(self):
   15           gtk.main()
   16
   17   print __name__
   18   if __name__ == "__main__":
   19       base = Base()
   20       base.main()

存盘后,可用两种方式运行该程序,一种是用:

debian:~# python base.py

另一种是用chmod命令设置base.py文件为可执行,再用shell的点号执行:

debian:~# chmod +x base.py
debian:~# ./base.py

下面简单解析一下base.py程序:

  • 程序第1行调用python来执行base.py脚本,每个python脚本的第一句都是这样的。

  • 第5-6行导入PyGTK模块,并限制PyGTK模块的版本为2.0。因为在一个系统中可同时存在多个PyGTK版本,如果没有版本限制,程序可能会出现混乱。

  • 9-15行定义一个Base类,用以创建一个窗口。

  • 第18-20行检查__name__变量是否是"__main__",如果是,则代表该脚本是当作脚本执行的,则执行下面的代码,否则,代表作为模块导入,不执行下面的代码。

  • 19行生成一个Base类的实例base,通过该实例调用Base类的main()方法启动GTK+的事件处理循环,等待X事件(击键、鼠标点击等)的发生。

下面是一个Hello World的例子:

#!/usr/bin/env python
#-*- encoding:utf-8 -*-

import pygtk
pygtk.require('2.0')
import gtk

class base:
#destroy信号的回调函数
        def destroy(self,widget,data=None):
                gtk.main_quit()

#clicked信号的回调函数
        def hello(self,widget,data):
                print 'hello ' + data + ' this is a button clicked() test'

#delete_event事件的回调函数
        def delete_event(self, widget, event, data=None):
                print "delete event occurred"
#如果delete_event事件返回假,则会触发destroy信号,从而关闭窗口。
#如果返回真,则不会关闭窗口。这个特性在当我们需要一个确认是否退出的选择对话框时是很有用。
                return False

        def __init__(self):
                self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
#设置窗口的delete_event信号触发delete_event函数
                self.window.connect("delete_event", self.delete_event)
#设置窗口的destroy信号触发destroy函数
                handler1 = self.window.connect("destroy",self.destroy)
                print "handler1 is:%d" % handler1
                self.window.set_title('PyGTK 测试 window')
                self.window.set_default_size(200,200)
                self.window.set_border_width(100)
#控制窗口出现的位置
                self.window.set_position(gtk.WIN_POS_CENTER)
#生成按钮实例
                self.button1 = gtk.Button()
                self.button2 = gtk.Button()
                self.button1.set_label('label1')
                self.button2.set_label('label2')
#设置按钮的clicked信号触发hello函数,并传递‘pyGTK’字符串参数给hello函数
                handler2 = self.button1.connect("clicked",self.hello,"pyGTK")
                print "handler2 is:%d" % handler2
#设置按钮的clicked信号触发self.window对象的gtk.Widget.destroy方法
                self.button1.connect_object("clicked", gtk.Widget.destroy, self.window)
#使用object.disconnect(id)方法取消handler2的功能
#               self.button.disconnect(handler2)
#设置一个不可见的横向的栏位self.box1
                self.box1 = gtk.HBox(gtk.False, 0)
#把box1放到窗口中
                self.window.add(self.box1)
#把button1部件放到box1中
                self.box1.pack_start(self.button1,True,True,0)
                self.button1.show()
#把button2部件放到button1部件之后
                self.box1.pack_start(self.button2,True,True,0)
                self.button2.show()
                self.box1.show()
                self.window.show()

        def main(self):
                gtk.main()

print __name__
if __name__ == "__main__":
        base = base()
        base.main()

2.2. 信号和回调函数

GTK+是一套事件驱动的工具包,也就是说,当执行gtk.main()后,进程会进入等待状态,等待事件的发生,从而触发相应的动作。

当事件发生时,相应的GTK+部件会发出信号(Signals),不同的Signals代表不同的事件,从而调用相应的函数。要使一个按钮完成一个动作。我们可以设置一个信号处理器来捕获这个按钮按下的信号,再调用相应的函数完成指定动作。这可通过GtkWidget方法来做,如:

handler_id = object.connect(name, func, func_data)

object是GtkWidget的一个实例,它将会发送一个信号。connect方法把实例与信号关联起来,并返回一个处理句柄,通过它我们可断开或阻塞这个句柄,也就是说使该操作失效。connect的第一个参数name代表你想捕获的信号,第二个参数代表你想调用的函数,第三个参数代表要传递给函数的参数。

第二个参数调用的函数我们叫它“回调函数”。定义方法如下:

def callback_func(widget, callback_data):

第一个参数是指向发出信号的widget的指针,第二个参数是一个指向func_data的指针,用以接收传递过来的数据。

如果回调函数是对象方法,则可写成:

def callback_method(self, widget, callback_data):

还有一种调用方法是connect_object(),它和connect()类似:

handler_id = object.connect_object(name, func, slot_object)
def callback_func(object)
def callback_method(self,object)

Chapter 3. 事件(events)

Chapter 4. 包装组件

使用gtk.container add()方法可把一个组件放到窗口里。当有多个组件需放到窗口时,就需用到水平方框和垂直方框这两个包装组件,一般来说,它们是不可见,只是用来规范布局。我们可把多个组件放到这两种方框中,摆放的位置可以是从左到右和从上到下。

要创建一个水平方框,用gtk.HBox()方法,要创建一个垂直方框调用gtk.VBox()方法。有了摆放组件的方框后,就可用pack_start()和pack_end()方法把组件放到这些方框中。pack_start()方法按从上到下,从左到右这种正常的顺序摆放组件,而pack_end()的摆放顺序和pack_start()刚刚相关,是按从下到上,从右到左摆放的。下面是一个示例: