含有章节索引的中文 文章模板
::-- ehu4ever [2005-08-08 03:52:40]
Contents
1. hello world庖丁解牛
填鸭也填够了,来点实战吧:)
我们还是用helloworld.py为例
1 #!/usr/bin/env python
2
3 # example helloworld.py
4
5 import pygtk
6 pygtk.require('2.0')
7 import gtk
8
9 class HelloWorld:
10
11 # This is a callback function. The data arguments are ignored
12 # in this example. More on callbacks below.
13 def hello(self, widget, data=None):
14 print "Hello World"
15
16 def delete_event(self, widget, event, data=None):
17 # If you return FALSE in the "delete_event" signal handler,
18 # GTK will emit the "destroy" signal. Returning TRUE means
19 # you don't want the window to be destroyed.
20 # This is useful for popping up 'are you sure you want to quit?'
21 # type dialogs.
22 print "delete event occurred"
23
24 # Change FALSE to TRUE and the main window will not be destroyed
25 # with a "delete_event".
26 return False
27
28 def destroy(self, widget, data=None):
29 print "destroy signal occurred"
30 gtk.main_quit()
31
32 def __init__(self):
33 # create a new window
34 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
35
36 # When the window is given the "delete_event" signal (this is given
37 # by the window manager, usually by the "close" option, or on the
38 # titlebar), we ask it to call the delete_event () function
39 # as defined above. The data passed to the callback
40 # function is NULL and is ignored in the callback function.
41 self.window.connect("delete_event", self.delete_event)
42
43 # Here we connect the "destroy" event to a signal handler.
44 # This event occurs when we call gtk_widget_destroy() on the window,
45 # or if we return FALSE in the "delete_event" callback.
46 self.window.connect("destroy", self.destroy)
47
48 # Sets the border width of the window.
49 self.window.set_border_width(10)
50
51 # Creates a new button with the label "Hello World".
52 self.button = gtk.Button("Hello World")
53
54 # When the button receives the "clicked" signal, it will call the
55 # function hello() passing it None as its argument. The hello()
56 # function is defined above.
57 self.button.connect("clicked", self.hello, None)
58
59 # This will cause the window to be destroyed by calling
60 # gtk_widget_destroy(window) when "clicked". Again, the destroy
61 # signal could come from here, or the window manager.
62 self.button.connect_object("clicked", gtk.Widget.destroy, self.window)
63
64 # This packs the button into the window (a GTK container).
65 self.window.add(self.button)
66
67 # The final step is to display this newly created widget.
68 self.button.show()
69
70 # and the window
71 self.window.show()
72
73 def main(self):
74 # All PyGTK applications must have a gtk.main(). Control ends here
75 # and waits for an event to occur (like a key press or mouse event).
76 gtk.main()
77
78 # If the program is run directly or passed as an argument to the python
79 # interpreter then create a HelloWorld instance and show it
80 if __name__ == "__main__":
81 hello = HelloWorld()
82 hello.main()
从第9行到76行定义了HelloWorld类,它包含了所有的callback和实例初始化method。这几个callback一个都不放过:
13,14行定义的hello()是在button被按下时被调用的,它的作用是在console上打出一句话“Hello World”。这里,我们忽略了hello()的参数self、widget和data,但是也只有这种easy到useless的callback才没有用它们。 data还定义了一个默认值None,以便在connect()没有传入相应值的情况下使用,这样就不会由于connect()只传两个参数而hello()这个callback要求有三个参数而报错了。
程序中还有一例子是connect()使用data来告诉hello()这个callback是哪个button被按下了:
def hello(self, widget, data=None): print "Hello World"
从16到26行就有点新鲜了,“delete_event”是由窗口管理器传给运行中的程序的。怎样处理就由自己,可以忽略,可以作出一些反映,也可以直接退出程序。
在这里“delete_event”这个event是和delete_event()这个callback相应的,delete_event()的返回值决定了程序下一步怎样走。如果是True就是甭理它,程序继续运行。如果是返回False就是“系统叫我destroy,我不得不destroy”,调用destroy(),退出程序。
def delete_event(widget, event, data=None): print "delete event occurred" return False
执行destroy()这个callback会退出程序,这是调用gtk.main_quit()实现的。它的意思是当控制权回到gtk.main()后,程序退出。
def destroy(widget, data=None): print "destroy signal occurred" gtk.main_quit()
32到71行定义了对象实例的初始化method:init,程序运行之后由它创建窗口的其它widget。
34行定义了一个窗口,但它直到window.show()执行之后才会显示。这个窗口的指针保存在变量self.window中以备后用。
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
41和46行是两个使用事件处理的例子,在这里是对self.window的事件处理:delete_event、destroy。delete_event这个事件是在窗口管理器要关闭程序窗口时发生的,或是程序中执行了GtkWidget.destroy()。destroy是在我们在delete_event()中返回False的情况下发生的。
self.window.connect("delete_event", self.delete_event) self.window.connect("destroy", self.destroy)
49行定义了程序主窗口的边框空白有10个pixel,这个区域是不能摆放widget。
self.window.set_border_width(10)
52行定义了一个gtk.Button,它的指针保存在self.button,这个按钮上写着“Hello World”。
self.button = gtk.Button("Hello World")
57行定义了对于“clicked”事件的处理,这个事件由hello()这个callback处理。这个例子中没有向hello()传什么数据。很明显,“clicked”的发生是因为我们在self.button上按了一下。
self.button.connect("clicked", self.hello, None)
由于hello()的data参数有一个默认的值,所以上面这一句中的None没有也可以。 这个按钮的功能是退出程序。62行说明了“destroy”是怎样产生的,可能来自窗口管理器,也可能是我们自己的程序。当按钮被按下时,程序先是调用了hello(),然后是执行62行之后connect的callback,我们可以在此之后定义n多的callback,它们都会按先后执行的。
因为我们要使用的GtkWidget.destroy()只接受一个参数(也就是要被destroy的窗口),所以使用connect_object()来进行事件处理的定义,在这其中传递一个窗口的指针。connect_object()按排窗口成为GtkWidget.destroy()的第一个参数,而不是按钮。
当gtk.Widget.destroy()被调用时,程序的主窗口将会发出“destroy”事件,接着调用了HelloWorld.destroy()来结束程序。
self.button.connect_object("clicked", gtk.Widget.destroy, self.window)
Line 65 is a packing call, which will be explained in depth later on in 对widget进行排版。其实这其中的道理是显而易见的,也就是告诉GTK+让这个按钮在它该出现的地方出现。注意,在GTK+中一个container只能放一个widget,如果要将多个widget放在一起,就要想另外的办法了。
self.window.add(self.button)
到现在为此,我们已经安排好一切了:所有的事件处理已经安排好;按钮也在他该呆的地方了。66到69行就要将按钮和主窗口显示在屏幕上。请注意这其中的顺序,是也显示按钮,再是主窗口。
self.button.show() self.window.show()
73到75行定义了main(),它调用gtk.main()来实现功能的。
def main(self): gtk.main()
80到82行是说当程序直接调用或是作为python解释器时可以运行。81行创建了一个HelloWorld实例,并将指针保存在变量hello中。82行调用了HelloWorld.main()启动了事件处理循环。
if __name__ == "__main__": hello = HelloWorld() hello.main()
一切都搞定了,当程序启动之后,我们在按钮上按一下,这个widget就发出了一个“clicked”事件,由于程序为这个事件建立了事件处理,HelloWorld.hello()就被调用了,接着下一个事件正理器被激活了,它调用了HelloWorld.destroy(),开始了destroy的过程。
事件的另外一个来源是窗口管理器,比如“delete_event”事件,这个事件在处理时HelloWorld.delete_event()被调用。它可能返回True或者是False,这个问题大家心里都有数了吧:)