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

::-- ehu4ever [2005-09-15 06:29:36]

1. Creating a Real Glade Application

Of course, the Glade version of our two-button application doesn't do anything, any more than the version that just used Python code did. In this section, we'll create a complex GUI, with some signal handlers, for an application called pyRAP. This is a chat-themed GUI that could be used as a client for the Python Chat Server described in Chapter 16.

Create a new Glade project called PyRAP, and create a new window as shown previously. To create a basic GUI, start with a Vertical Box widget, also shown previously. Click the Vertical Box in the widget palette, and then click the crosshatch marks in the new window to place it there. When Glade asks you

how many rows you want in your Vertical Box, enter 3 (as opposed to the two-row box created in the previous example).

Put a Menu Bar widget in the top row, and a Status Bar widget in the bottom row. You should now have a GUI that looks a lot like the application interface most people have come to expect, with an empty space in the middle (see Figure 13-14).

Figure 13-14

That empty middle container (note the cross-hatching) is where we'll put the guts of our application. For starters, we'll just have pyRAP take the contents of an Input widget and write it to another widget. To do this, we'll split our central container into two portions with a two-column Horizontal Box, as shown in Figure 13-15.

Figure 13-15

Now we've got a window that is divided into three portions by a vertical box. The middle portion of the Vertical Box is itself divided in two by a Horizontal Box. Let's go one step further and use another Vertical Box to divide the left portion of the Horizontal Box into three sections, as shown in Figure 13-16.

Figure 13-16

That's enough layout widgets. Now it's time to place some real widgets. In the Vertical Box you just created, put a Label in the top slot, a Text Entry in the middle slot, and a Button in the bottom slot. Your GUI should now look like the window shown in Figure 13-17.

Figure 13-17

Note that the label and button widgets appear with some rather bland default text. In a little bit, you'll change that text using the properties sheets for those widgets. Right now, though, let's fill up the only remaining slot in your GUI with a Text View widget, as shown in Figure 13-18.

Figure 13-18

Let's change that default text. Select the label and the button in turn, and use the property sheet to set their Label properties (see Figure 13-19). As you change the default text, you'll see the text in the mockup change as well.

Figure 13-19

Now your mock-up should look like the GUI for a real application (see Figure 13-20).

What you're seeing is a Label, a Text Entry, and a Button on the left side, and a Text View on the right side. GTK supports most of the widgets you can expect from any windowing interface - Combo-Boxes, Spin Buttons for numeric input, and so on. The only difficult part of GTK is understanding and using Trees and Lists and properly designing your application to handle threads. Now you've reached the fun part: deciding what to do with this application.

Figure 13-20

Now it's time to learn how to connect the application to some Python code. Save your Glade project and let's start writing PyRAP . py, the code for the application that uses it:

   1 #!/usr/bin/env python import time
   2 import findgtk
   3 import gtk.glade
   4 
   5 class PyRAPGUI:
   6         def __init__(self) :
   7                 self.wTree = gtk.glade.XML("PyRAP.glade", "window1")
   8 
   9 if __name__ == '__main __': PyRAPGUI ( )
  10         try:
  11                 gtk.threads_init()
  12         except:
  13                 print "No threading was enabled when you compiled pyGTK!"
  14                 import sys
  15                 sys.exit(1)
  16         gtk.threads_enter() gtk.main()
  17         gtk.threads_leave()

This code is just a skeleton, and it has the same problem as the earlier Glade example. You can enter text into the Text Enter widget, but clicking the button doesn't do anything. You need to set up a signal so the program does something when the button is clicked.

Go back into Glade, and select the Send button in your mock-up. Select the Properties View. Add a signal that's activated when the Send button is clicked by clicking first on the Signals tab, and then on the ellipses (...) button next to the Signal: label (see Figure 13-21). Select the clicked signal and then click Add. When the GUI gets a click on the button, it'll generate a signal on_button1_clicked for pyGTK to process.

Figure 13-21

Click the window1 object in the main screen of Glade to bring focus on the main widget. Next, go to the window's properties sheet. Carry out the same process as before to add an on_window1_destroy signal for the window widget.

Now let's redo PyRAP . py to respond to those signals. When you kill the window, the program will exit, as in the previous examples. When you click the Send button, PyRAP will copy to the Text View widget on the right anything you typed into the Text Entry widget on the left:

   1 #!/usr/bin/env python import findgtk
   2 import gtk
   3 import time
   4 
   5 class PyRAPGUI:
   6         def __init__(self) :
   7                 self.wTree = gtk.glade.XML ("PyRAP.glade", "window1")
   8                 dic={ "on_window1_destroy" : self.quit,
   9                         "on_button1_clicked" : self.send,
  10                         }
  11                 self.wTree.signal_autoconnect (dic)
  12                 self.username="Bob"
  13                 #setup the text view to act as a log window 
  14                 self.logwindowview=self.wTree.get_widget("textview1")
  15                 self.logwindow=gtk.TextBuffer(None)
  16                 self.logwindowview.set_buffer(self.logwindow)
  17                 return
  18 
  19         #Handlers for the GUI signals
  20         def quit(self,obj):
  21                 "Handles the 'destroy' signal of the window."
  22                 gtk.main_quit()
  23                 sys.exit(1)
  24         def send(self,obj):
  25         "Handles the 'clicked' signal of the button."
  26         message=self.wTree.get_widget("entry1").get_text()
  27         print "Message=%s" % message
  28         self.log(self.username + ": " + message, "black")
  29 
  30         def log(self,message,color,enter="\n"):
  31         """
  32         A helper method for the "send" GUI signal handler:
  33         logs a message to the log window and scrolls the window to the bottom
  34         """ message=message+enter
  35 
  36         buffer = self.logwindow
  37         iter = buffer.get_end_iter()
  38         #gtk versioning avoidance
  39         if color != "black":
  40                 tag = buffer.create_tag()
  41                 tag.set_property("foreground", color)
  42                 self.logwindow.insert_with_tags(buffer.get_end_iter(), message, tag)
  43         else:
  44                 self.logwindow.insert(iter, message)
  45         #gtk.FALSE and gtk.TRUE on older pyGTK
  46         mark = buffer.create_mark("end", buffer.get_end_iter(), False)
  47         self.logwindowview.scroll_to_mark(mark,0.05,True,0.0,1.0)
  48         #print "Exited log function"
  49 
  50 if __name__ == '__main __':
  51         PyRAPGUI()
  52         try:
  53                 gtk.threads_init()
  54         except:
  55                 print "No threading was enabled when you compiled pyGTK!"
  56                 import sys
  57                 sys.exit(1)
  58         gtk.threads_enter()
  59         gtk.main()
  60         gtk.threads_leave()

First, we initialize the Text View widget to contain a text buffer. Then we must handle writing into the text buffer and scrolling it down so it always displays the latest message. As a bonus, we also put in some code to display the text in different colors, if desired. We'll probably use that later. As you can see, with a few widgets and two signals, we've created the bare bones of a working GUI for a text messenger system (see Figure 13-22).

Figure 13-22

The exciting thing about Glade is that you can go from concept to working demo in a couple of hours. As you revise your program, the GUI can morph completely, without ever affecting your code. Of course, pyRAP is lacking networking code in this example, but that could be fleshed out with either socket calls