## page was renamed from zhArticleTemplate ##language:zh #pragma section-numbers on ''' 含有章节索引的中文 文章模板 ''' ::-- ehu4ever [<>] <> = hello world庖丁解牛 = 填鸭也填够了,来点实战吧:) 我们还是用helloworld.py为例 {{{#!python #!/usr/bin/env python # example helloworld.py import pygtk pygtk.require('2.0') import gtk class HelloWorld: # This is a callback function. The data arguments are ignored # in this example. More on callbacks below. def hello(self, widget, data=None): print "Hello World" def delete_event(self, widget, event, data=None): # If you return FALSE in the "delete_event" signal handler, # GTK will emit the "destroy" signal. Returning TRUE means # you don't want the window to be destroyed. # This is useful for popping up 'are you sure you want to quit?' # type dialogs. print "delete event occurred" # Change FALSE to TRUE and the main window will not be destroyed # with a "delete_event". return False def destroy(self, widget, data=None): print "destroy signal occurred" gtk.main_quit() def __init__(self): # create a new window self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) # When the window is given the "delete_event" signal (this is given # by the window manager, usually by the "close" option, or on the # titlebar), we ask it to call the delete_event () function # as defined above. The data passed to the callback # function is NULL and is ignored in the callback function. self.window.connect("delete_event", self.delete_event) # Here we connect the "destroy" event to a signal handler. # This event occurs when we call gtk_widget_destroy() on the window, # or if we return FALSE in the "delete_event" callback. self.window.connect("destroy", self.destroy) # Sets the border width of the window. self.window.set_border_width(10) # Creates a new button with the label "Hello World". self.button = gtk.Button("Hello World") # When the button receives the "clicked" signal, it will call the # function hello() passing it None as its argument. The hello() # function is defined above. self.button.connect("clicked", self.hello, None) # This will cause the window to be destroyed by calling # gtk_widget_destroy(window) when "clicked". Again, the destroy # signal could come from here, or the window manager. self.button.connect_object("clicked", gtk.Widget.destroy, self.window) # This packs the button into the window (a GTK container). self.window.add(self.button) # The final step is to display this newly created widget. self.button.show() # and the window self.window.show() def main(self): # All PyGTK applications must have a gtk.main(). Control ends here # and waits for an event to occur (like a key press or mouse event). gtk.main() # If the program is run directly or passed as an argument to the python # interpreter then create a HelloWorld instance and show it if __name__ == "__main__": hello = HelloWorld() 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 '''[[self:pygtk_packing|对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,这个问题大家心里都有数了吧:)