含有章节索引的中文 文章模板

::-- ehu4ever [2005-08-08 03:52:40]

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,这个问题大家心里都有数了吧:)