特殊:Badtitle/NS100:UMEGuide/ApplicationDevelopment/GladeWithPythonForUMEHildon:修订间差异

来自Ubuntu中文
跳到导航跳到搜索
Wikibot留言 | 贡献
无编辑摘要
Wikibot留言 | 贡献
无编辑摘要
第36行: 第36行:
<pre><nowiki>
<pre><nowiki>
class GladeTestApp():
class GladeTestApp():
"""pygtk-glade-hildon demo project"""
    """pygtk-glade-hildon demo project"""
def <u>init</u>(self):
 
#make the hildon program
    def __init__(self):
self.program = hildon.Program()
 
self.program.<u>init</u>()
        #make the hildon program
#make the hildon window and add to program
        self.program = hildon.Program()
self.window = hildon.Window()
        self.program.__init__()
self.window.set_title("PyGlade")
       
self.program.add_window(self.window
        #make the hildon window and add to program
        self.window = hildon.Window()
        self.window.set_title("PyGlade")
        self.program.add_window(self.window
</nowiki></pre>
</nowiki></pre>
As you can see, the Hildon Program is created and assigned to <code><nowiki>self.program</nowiki></code>. And, the Hildon Window is created and assigned to <code><nowiki>self.window</nowiki></code>. Pretty straightforward.  
As you can see, the Hildon Program is created and assigned to <code><nowiki>self.program</nowiki></code>. And, the Hildon Window is created and assigned to <code><nowiki>self.window</nowiki></code>. Pretty straightforward.  
第51行: 第54行:
The .glade file is imported inside <code><nowiki>GladeTestApp</nowiki></code>'s constructor. The code looks like this:
The .glade file is imported inside <code><nowiki>GladeTestApp</nowiki></code>'s constructor. The code looks like this:
<pre><nowiki>
<pre><nowiki>
self.glade_file = "pygladeui.glade"
        self.glade_file = "pygladeui.glade"
self.wTree=gtk.glade.XML(self.glade_file)
        self.wTree=gtk.glade.XML(self.glade_file)
</nowiki></pre>
</nowiki></pre>
The first line defines a variable (<code><nowiki>self.glade_file</nowiki></code>) and assigns it the file name of the .glade file, in this case <code><nowiki>pygladeui.glade</nowiki></code>.  
The first line defines a variable (<code><nowiki>self.glade_file</nowiki></code>) and assigns it the file name of the .glade file, in this case <code><nowiki>pygladeui.glade</nowiki></code>.  
第61行: 第64行:
Here's the Python code that fetches the VBox from the imported glade file:
Here's the Python code that fetches the VBox from the imported glade file:
<pre><nowiki>
<pre><nowiki>
#reparent the vbox1 from glade to self.window
        #reparent the vbox1 from glade to self.window
self.vbox1 = self.wTree.get_widget("vbox1")
        self.vbox1 = self.wTree.get_widget("vbox1")
self.reparent_loc(self.vbox1, self.window)
        self.reparent_loc(self.vbox1, self.window)
</nowiki></pre>
</nowiki></pre>
The first non-comment code line gets the specified GTK VBox and assigns it to the <code><nowiki>self.vbox1</nowiki></code> variable.  
The first non-comment code line gets the specified GTK VBox and assigns it to the <code><nowiki>self.vbox1</nowiki></code> variable.  
第72行: 第75行:
The following Python code shows how to get the imported the GTK menu that's named <code><nowiki>menu1</nowiki></code>, assign it to <code><nowiki>self.menuGlade</nowiki></code>, and then set the Hildon Program to use this as its common menu.  
The following Python code shows how to get the imported the GTK menu that's named <code><nowiki>menu1</nowiki></code>, assign it to <code><nowiki>self.menuGlade</nowiki></code>, and then set the Hildon Program to use this as its common menu.  
<pre><nowiki>
<pre><nowiki>
#get menu from glade and reparent as common menu in hildon program
        #get menu from glade and reparent as common menu in hildon program
self.menuGlade = self.wTree.get_widget("menu1")
        self.menuGlade = self.wTree.get_widget("menu1")
self.program.set_common_menu(self.menuGlade)   
        self.program.set_common_menu(self.menuGlade)   
</nowiki></pre>
</nowiki></pre>
=== Source ===
=== Source ===
第83行: 第86行:
import hildon
import hildon
import gtk.glade
import gtk.glade
class GladeTestApp():
class GladeTestApp():
"""pygtk-glade-hildon demo project"""
    """pygtk-glade-hildon demo project"""
def <u>init</u>(self):
 
#make the hildon program
    def __init__(self):
self.program = hildon.Program()
 
self.program.<u>init</u>()
        #make the hildon program
#make the hildon window and add to program
        self.program = hildon.Program()
self.window = hildon.Window()
        self.program.__init__()
self.window.set_title("PyGlade")
       
self.program.add_window(self.window)
        #make the hildon window and add to program
#receive signal to close window from framework close button   
        self.window = hildon.Window()
if (self.window):
        self.window.set_title("PyGlade")
self.window.connect("destroy", gtk.main_quit)
        self.program.add_window(self.window)
#import the glade file and assign to self.wTree
       
self.glade_file = "pygladeui.glade"
        #receive signal to close window from framework close button   
self.wTree = gtk.glade.XML(self.glade_file)
        if (self.window):
#reparent the vbox1 from glade to self.window
            self.window.connect("destroy", gtk.main_quit)
self.vbox1 = self.wTree.get_widget("vbox1")
       
self.reparent_loc(self.vbox1, self.window)
        #import the glade file and assign to self.wTree
#get menu from glade and reparent as common menu in hildon program
        self.glade_file = "pygladeui.glade"
self.menuGlade = self.wTree.get_widget("menu1")
        self.wTree = gtk.glade.XML(self.glade_file)
self.program.set_common_menu(self.menuGlade)         
       
#get quit menu item and connect signal
        #reparent the vbox1 from glade to self.window
self.menuItem_quit = self.wTree.get_widget("quit1")
        self.vbox1 = self.wTree.get_widget("vbox1")
self.menuItem_quit.connect("activate", gtk.main_quit)
        self.reparent_loc(self.vbox1, self.window)
#get hbox1 in order to modify contents based on user actions
       
self.hbox1 = self.wTree.get_widget("hbox1")
        #get menu from glade and reparent as common menu in hildon program
#get label1 for use     
        self.menuGlade = self.wTree.get_widget("menu1")
self.label1 = self.wTree.get_widget("label1")         
        self.program.set_common_menu(self.menuGlade)         
self.controlBar = hildon.Controlbar()
       
self.controlBar.set_min(0)  
        #get quit menu item and connect signal
self.controlBar.set_max(50)  
        self.menuItem_quit = self.wTree.get_widget("quit1")
self.controlBar.set_value(15)  
        self.menuItem_quit.connect("activate", gtk.main_quit)
self.controlBar.connect("value-changed", self.control_changed, self.label1)
 
self.menuItem_controlBar = self.wTree.get_widget("controlBar")
        #get hbox1 in order to modify contents based on user actions
self.menuItem_controlBar.connect("activate", self.controlBar_pressed, self.hbox1, self.controlBar, self.label1)
        self.hbox1 = self.wTree.get_widget("hbox1")
self.dateEditor = hildon.DateEditor()  
 
self.dateEditor.set_year(2006)  
        #get label1 for use     
self.dateEditor.set_month(4)  
        self.label1 = self.wTree.get_widget("label1")         
self.dateEditor.set_day(20)   
 
self.menuItem_dateEditor = self.wTree.get_widget("dateEditor")
        self.controlBar = hildon.Controlbar()
self.menuItem_dateEditor.connect("activate", self.dateEditor_pressed, self.hbox1, self.dateEditor, self.label1)         
        self.controlBar.set_min(0)  
#get button1 and connect a signal handler
        self.controlBar.set_max(50)  
self.button1 = self.wTree.get_widget("button1")
        self.controlBar.set_value(15)  
if (self.button1):
        self.controlBar.connect("value-changed", self.control_changed, self.label1)
self.button1.connect("pressed", self.button1_pressed, self.label1)
       
#destroy the gtk window imported from glade
        self.menuItem_controlBar = self.wTree.get_widget("controlBar")
self.gtkWindow = self.wTree.get_widget("window1")
        self.menuItem_controlBar.connect("activate", self.controlBar_pressed, self.hbox1, self.controlBar, self.label1)
self.gtkWindow.destroy()
 
#display everything
        self.dateEditor = hildon.DateEditor()  
self.window.show_all()
        self.dateEditor.set_year(2006)  
def run(self):
        self.dateEditor.set_month(4)  
gtk.main()
        self.dateEditor.set_day(20)   
     
        self.menuItem_dateEditor = self.wTree.get_widget("dateEditor")
        self.menuItem_dateEditor.connect("activate", self.dateEditor_pressed, self.hbox1, self.dateEditor, self.label1)         
       
        #get button1 and connect a signal handler
        self.button1 = self.wTree.get_widget("button1")
        if (self.button1):
            self.button1.connect("pressed", self.button1_pressed, self.label1)
       
        #destroy the gtk window imported from glade
        self.gtkWindow = self.wTree.get_widget("window1")
        self.gtkWindow.destroy()
       
        #display everything
        self.window.show_all()
 
    def run(self):
        gtk.main()
 
# signal handlers
# signal handlers
def menuItem_quit1_pressed(self, widget):
   
gtk.main_quit  
    def menuItem_quit1_pressed(self, widget):
def button1_pressed(self, widget, label):
        gtk.main_quit  
label.set_label("new label")     
 
    def button1_pressed(self, widget, label):
        label.set_label("new label")    
      
# controlBar
# controlBar
def controlBar_pressed(self, widget, hbox, controlBar, label):
 
self.dechild_hbox(hbox)
    def controlBar_pressed(self, widget, hbox, controlBar, label):
hbox.add(controlBar)
        self.dechild_hbox(hbox)
controlBar.show()
        hbox.add(controlBar)
label.set_text("ControlBar")
        controlBar.show()
def control_changed(self, widget, label):  
        label.set_text("ControlBar")
label.set_text(" %s of %s" % (widget.get_value(), widget.get_max()))
 
    def control_changed(self, widget, label):  
        label.set_text(" %s of %s" % (widget.get_value(), widget.get_max()))
 
# dateEditor
# dateEditor
def dateEditor_pressed(self, widget, hbox, dateEditor, label):
 
self.dechild_hbox(hbox)
    def dateEditor_pressed(self, widget, hbox, dateEditor, label):
hbox.add(dateEditor)
        self.dechild_hbox(hbox)
label.set_text("DateEditor")
        hbox.add(dateEditor)
dateEditor.show()
        label.set_text("DateEditor")
        dateEditor.show()
 
#utility
#utility
def dechild_hbox(self, hbox_widgets):
 
children = hbox_widgets.get_children()
    def dechild_hbox(self, hbox_widgets):
for child in children:
        children = hbox_widgets.get_children()
hbox_widgets.remove(child)
        for child in children:
def reparent_loc(self, widget, newParent):
            hbox_widgets.remove(child)
widget.reparent(newParent)
 
if <u>name</u> == "<u>main</u>":
    def reparent_loc(self, widget, newParent):
app = GladeTestApp()
        widget.reparent(newParent)
app.run()
 
if __name__ == "__main__":
    app = GladeTestApp()
    app.run()
</nowiki></pre>
</nowiki></pre>
==== Makefile ====
==== Makefile ====
第179行: 第213行:
@install -m 755 -D desktop.txt ${DESTDIR}/usr/share/applications/pyglade.desktop
@install -m 755 -D desktop.txt ${DESTDIR}/usr/share/applications/pyglade.desktop
@install -m 755 -D pyglade_26.png ${DESTDIR}/usr/share/icons/hicolor/22x22/apps/pyglade_26.png
@install -m 755 -D pyglade_26.png ${DESTDIR}/usr/share/icons/hicolor/22x22/apps/pyglade_26.png
clean:
clean:
@rm -f ${APPDIR}/main.py
@rm -f ${APPDIR}/main.py

2007年12月6日 (四) 10:58的版本

{{#ifexist: :UMEGuide/ApplicationDevelopment/GladeWithPythonForUMEHildon/zh | | {{#ifexist: UMEGuide/ApplicationDevelopment/GladeWithPythonForUMEHildon/zh | | {{#ifeq: {{#titleparts:UMEGuide/ApplicationDevelopment/GladeWithPythonForUMEHildon|1|-1|}} | zh | | }} }} }} {{#ifeq: {{#titleparts:UMEGuide/ApplicationDevelopment/GladeWithPythonForUMEHildon|1|-1|}} | zh | | }}

Purpose

This wiki page explains how to import an application's user interface that was made with Glade into Python in order to make a UME/Hildon application. In particular, it covers:

  • How to import a Glade user interface definition file into Python
  • How to access objects defined in Glade and give them local Python names
  • How to reparent Glade widgets to the required Python Hildon Window
  • How to get a GTK Menu defined in Glade and set it as the Hildon Program menu in Python

Terminology: What's "reparenting"? The top level window in a UME application is - by definition - a Hildon Window. However, Glade can only create a GTK Window, not the Hildon Window you need. (When using Glade, you need a GTK Window as a top-level widget so that you can add other child widgets to it). To deal with this mismatch, you create a real Hildon Window in your Python and then "reparent" the GTK Window's direct children to it.

Prerequisites

  • Glade
  • A UME development/build/run environment
  • Understanding of the files and directories required by a UME Desktop Python application -- see

Files and Directories for Adding a Python Application to UME

  • Basic Python knowledge

Packages

You will need the following packages installed in the UME target:

  • python-gtk2
  • python-hildon-1.2
  • python-glade2

You can install each by entering the target UME root directory (the target chroot when working from Image-Creator) and executing the usual apt-get install (package name) command.

Using Glade

This how-to assumes basic knowledge of how to use Glade. However, even if you've never used it before, rest assured that it's quite easy. Glade is a graphical tool for creating a GTK user interface by dragging widgets onto a canvas or into other widgets (in which case they become children) and then optionally selecting widgets and modifying their properties. The result is an XML file with the .glade extension that contains a description of the user interface that can be imported into various languages, including Python. After importing the .glade file, you can access the widgets using the names you gave them in Glade and then use them programmatically. As noted, one important point is how to deal with the fact that Glade cannot create a Hildon Window. It can only create a GTK Window, and indeed it requires one as a parent for most other widgets (but not menus). So, in Glade, you create the GTK Window and add widgets to it, then, in your Python you "reparent" the GTK Window's child widgets to your real Hildon Window. To minimize reparenting, this example program's root window has only one child, a GTK VBox widget, which in turn contains child widgets. So, this VBox must be reparented from the GTK Window to a Hildon Window. Let's take a look at these steps in a little more detail, but first let's review the Python program's basic structure.

This Python program's structure

Note: Please see main.py main.py source at the end of this page. This is a simple Python program. Among the usual imports at the top is: import gtk.glade, which is required to import the .glade file. The program has one class, GladeTestApp, whose constructor creates the Hildon Program and Hildon Window, imports the .glade file, assigns Glade objects local names, reparents a widget, sets the Hildon program menu from a Glade-defined menu, sets up signal handlers for user events, and other things. The class is instantiated as an object named app, and it's run() method is executed. Let's start by examining how the constructor creates the Hildon Program and Hildon Window.

Creating the Hildon Program and Hildon Window

Here's the top of the GladeTestApp class, showing the beginning of its constructor.

class GladeTestApp():
    """pygtk-glade-hildon demo project"""

    def __init__(self):

        #make the hildon program
        self.program = hildon.Program()
        self.program.__init__()
        
        #make the hildon window and add to program
        self.window = hildon.Window()
        self.window.set_title("PyGlade")
        self.program.add_window(self.window

As you can see, the Hildon Program is created and assigned to self.program. And, the Hildon Window is created and assigned to self.window. Pretty straightforward. Next, we'll import the .glade file.

Importing the .glade file

The .glade file is imported inside GladeTestApp's constructor. The code looks like this:

        self.glade_file = "pygladeui.glade"
        self.wTree=gtk.glade.XML(self.glade_file)

The first line defines a variable (self.glade_file) and assigns it the file name of the .glade file, in this case pygladeui.glade. The second line actually imports all user interface objects from the specified .glade file into a new variable named self.wTree. Now, all the objects defined in the .glade file can be retrieved from self.wTree and can be assigned local names for programmatic use. They are retrieved using the names they were given (or assigned by default) when using Glade, as shown next.

Reparenting to Hildon Window

As noted, the GTK window made with Glade contains a GTK VBox widget that contains all other application widgets (except for the menu, discussed below). When making this VBox widget with Glade, I gave it the following name: vbox1. (The widget's name is viewed/set in Glade by selecting it and looking at its "properties" in the Properties window.) Here's the Python code that fetches the VBox from the imported glade file:

        #reparent the vbox1 from glade to self.window
        self.vbox1 = self.wTree.get_widget("vbox1")
        self.reparent_loc(self.vbox1, self.window)

The first non-comment code line gets the specified GTK VBox and assigns it to the self.vbox1 variable. The second reparents the VBox from the GTK window made in Glade to the Hildon Window made in Python that's named self.window with the reparent_loc() function. That's it for reparenting! Let's take a look at importing the GTK menu made in Glade and setting it as the application's Hildon menu.

Getting the menu and making it a Hildon Menu

In Hildon, you create a GTK menu and add it to the Hildon Program with the set_common_menu(GTK.menu) function, as mentioned previously. The following Python code shows how to get the imported the GTK menu that's named menu1, assign it to self.menuGlade, and then set the Hildon Program to use this as its common menu.

        #get menu from glade and reparent as common menu in hildon program
        self.menuGlade = self.wTree.get_widget("menu1")
        self.program.set_common_menu(self.menuGlade)  

Source

main.py

import pygtk
import gtk
import hildon
import gtk.glade

class GladeTestApp():
    """pygtk-glade-hildon demo project"""

    def __init__(self):

        #make the hildon program
        self.program = hildon.Program()
        self.program.__init__()
        
        #make the hildon window and add to program
        self.window = hildon.Window()
        self.window.set_title("PyGlade")
        self.program.add_window(self.window)
        
        #receive signal to close window from framework close button  
        if (self.window):
            self.window.connect("destroy", gtk.main_quit)
        
        #import the glade file and assign to self.wTree
        self.glade_file = "pygladeui.glade"
        self.wTree = gtk.glade.XML(self.glade_file)
        
        #reparent the vbox1 from glade to self.window
        self.vbox1 = self.wTree.get_widget("vbox1")
        self.reparent_loc(self.vbox1, self.window)
        
        #get menu from glade and reparent as common menu in hildon program
        self.menuGlade = self.wTree.get_widget("menu1")
        self.program.set_common_menu(self.menuGlade)        
        
        #get quit menu item and connect signal
        self.menuItem_quit = self.wTree.get_widget("quit1")
        self.menuItem_quit.connect("activate", gtk.main_quit)
  
        #get hbox1 in order to modify contents based on user actions
        self.hbox1 = self.wTree.get_widget("hbox1")

        #get label1 for use    
        self.label1 = self.wTree.get_widget("label1")        

        self.controlBar = hildon.Controlbar()
        self.controlBar.set_min(0) 
        self.controlBar.set_max(50) 
        self.controlBar.set_value(15) 
        self.controlBar.connect("value-changed", self.control_changed, self.label1)
        
        self.menuItem_controlBar = self.wTree.get_widget("controlBar")
        self.menuItem_controlBar.connect("activate", self.controlBar_pressed, self.hbox1, self.controlBar, self.label1)

        self.dateEditor = hildon.DateEditor() 
        self.dateEditor.set_year(2006) 
        self.dateEditor.set_month(4) 
        self.dateEditor.set_day(20)  
      
        self.menuItem_dateEditor = self.wTree.get_widget("dateEditor")
        self.menuItem_dateEditor.connect("activate", self.dateEditor_pressed, self.hbox1, self.dateEditor, self.label1)        
        
        #get button1 and connect a signal handler
        self.button1 = self.wTree.get_widget("button1")
        if (self.button1):
            self.button1.connect("pressed", self.button1_pressed, self.label1)
        
        #destroy the gtk window imported from glade
        self.gtkWindow = self.wTree.get_widget("window1")
        self.gtkWindow.destroy()
        
        #display everything
        self.window.show_all()

    def run(self):
        gtk.main()

# signal handlers
    
    def menuItem_quit1_pressed(self, widget):
        gtk.main_quit 

    def button1_pressed(self, widget, label):
        label.set_label("new label")     
    
# controlBar

    def controlBar_pressed(self, widget, hbox, controlBar, label):
        self.dechild_hbox(hbox)
        hbox.add(controlBar)
        controlBar.show()
        label.set_text("ControlBar")

    def control_changed(self, widget, label): 
        label.set_text(" %s of %s" % (widget.get_value(), widget.get_max()))

# dateEditor

    def dateEditor_pressed(self, widget, hbox, dateEditor, label):
        self.dechild_hbox(hbox)
        hbox.add(dateEditor)
        label.set_text("DateEditor")
        dateEditor.show()

#utility

    def dechild_hbox(self, hbox_widgets):
        children = hbox_widgets.get_children()
        for child in children:
            hbox_widgets.remove(child)

    def reparent_loc(self, widget, newParent):
        widget.reparent(newParent)

if __name__ == "__main__":
    app = GladeTestApp()
    app.run()

Makefile

BINDIR = ${DESTDIR}/usr/bin/
APPDIR = ${DESTDIR}/usr/share/pyglade
all: 
install:
	@mkdir -p ${BINDIR}
	@mkdir -p ${APPDIR}
	@install -m 755 -D main.py ${APPDIR}/main.py
	@install -m 755 -D pygladeui.glade ${APPDIR}/pygladeui.glade
	@install -m 755 -D executable.txt ${BINDIR}/pyglade
	@install -m 755 -D desktop.txt ${DESTDIR}/usr/share/applications/pyglade.desktop
	@install -m 755 -D pyglade_26.png ${DESTDIR}/usr/share/icons/hicolor/22x22/apps/pyglade_26.png

clean:
	@rm -f ${APPDIR}/main.py
	@rm -f ${APPDIR}/pygladeui.glade
	@rm -f ${BINDIR}/pyglade
	@rm -f ${DESTDIR}/usr/share/applications/pyglade.desktop
	@rm -f ${DESTDIR}/usr/share/icons/${THEME}/22x22/apps/pyglade_26.png

re.