[LinuxFocus-icon]
首页  |  站点地图  |  索引  |  搜索

新闻 | 过往期刊 | 链接 | 关于LF
This document is available in: English  Castellano  ChineseGB  Deutsch  Francais  Nederlands  Portugues  Turkce  

Hilaire Fernandes
by Hilaire Fernandes
<hilaire(at)ofset.org>

关于作者:

Hilaire Fernandes 是 OFSET 的副总裁, OFSET是一个为Gnome项目教学做推广及开发免费软件的组织。他写过一个名为Dr. Geo的动态几何结构软件。目前他正致力于另一个Gnome项目教学的数学软件Dr. Genius的工作。


目录:

 

Developing Gnome applications with Python (part 2)

Gnome

摘要:

这些系列文章主要是为那些在Gnome及GNU/LINUX环境中进行程序开发的入门者而写的。为什么会选择Python作为开发语言呢?主要是因为入门者通常能够更快地熟悉Python而不是那些编译语言(比如说C语言)。要理解这些文章需要具备在Python下编程的基础。



 

所需工具:

所需的软件已经列在了这些系列文章的开始部分

您还需要:

关于带LibGlade库的Python-Gnome的安装过程及使用方法同样也已经列在了这些系列文章的开始部分。

 

Drill, 我们提供的练习

第一篇文章的目的是为了演示在用Gnome、Glade、LibGlade库以及Python所配置的运行环境下分别用脚本模式和交互模式写的程序的不同组成。

示例使用了GnomeCanvas部件。这个例子不仅向我们做了一个生动的展示,而且告诉我们在这样的配置下做开发是很容易的。

在随后的一个章节,建议在一个框架结构下进行,以便于说明Gnome的不同部件。本文集中讲述一个框架结构的创建生成。此后的文章将在这个框架结构的基础上加入更多的特征部件来举例说明大部分的Gnome部件。

在这里,我们的这个框架结构名字叫做Drill(训练)。它将作为教学过程中的一个基础平台,应用在我们的例子及练习中。这些例子作为独立的部分向我们演示那些部件的使用方法。

 

用Glade创建一个界面

部件:

我们的应用程序窗口是用Glade来创建的。类似于在前面的文章中您创建的第一个Gnome应用程序窗口,但在那个窗口中您不得不删除无用的图标和菜单。

Drill的主要部分被GtkPaned部件划分为两个工作空间。(见下图)

[Drill window]
Fig. 1 - Drill main window

两个工作空间被垂直划分,中间的可控边界可以左右移动,用以调整每个工作空间的大小。左边的工作空间包含有树状结构部件(GtkTree),右边的工作空间暂时是空的,以后就是在这个位置根据使用者的要求添加分支。

通过Glade查看Drill的界面让我们能够进一步了解它的各个组成的构架。(见下图)

[widgets in tree]
Fig. 2 - tree view of Drill

您在上图 Fig. 2 中可以看到,hpanedTree部件 (隶属于GtkPaned类型)仅仅包含了一个部件, 即左边的frame2(隶属于GtkFrame类型), frame2包含了exerciceTree部件。它能更好地将一个GtkFrame部件导入一个GtkPaned部件中(使用GTK_SHADOW_IN类型的shadow),这样就避免了遮挡住可控边界。

一个Gnome对话框“About Drill”看起来就象下面这样:

[Dialog window]
Fig. 3 - Dialog box "About Drill"

它的不同部分可以通过Glade在部件属性窗口中修改。

部件和处理函数的名称:

在Python下用下述的这些部件名称来使用它们:

Gnome应用程序窗口:
drillApp

可划分的分支树:
hpanedTree

分支树:
exerciceTree

Gnome的“关于”对话框 :
about

您可以在图Fig. 2中看到这些部件的名称。

我们在这里简单地列出处理函数的名称,如果您需要了解关于这个主题更多的信息,请参阅这些系列文章的第一部分

部件名称 信号 处理方式
about clicked gtk_widget_destroy
about close gtk_widget_destroy
about destroy gtk_widget_destroy
button1 (Icon New in the
tool bar)
clicked on_new_activate
new activate on_new_activate
drillApp destroy on_exit_activate
exit activate on_exit_activate
about activate on_about_activate

最后调整:

通过Glade可以指定部件的几何结构。在我们的例子中,您可以通过属性面板中的Common Tab将drillApp的大小设定为400x300,您也可以设定水平分割线的位置为100来替代1。

现在exerciceTree部件将被调整为单选模式(一次只能选择一个分支)。实际上,一次仅有一个分支被选中。在属性面板中,选择Selection -> Single,这个部件的其它选项并不重要。

瞧,这些都离不开我们的Drill。我们将在下一章中开始我们的开发练习。现在,让我们看看在Python下如何应用这个界面并利用GtkTree部件。

 

Python代码

完整的源码可以在这篇文档的最后找到,您需要将它和drill.glade保存在同一个目录下。

 

所需模块(modules)

from gtk import *
from gnome.ui import *
from GDK import *
from libglade import *

 

使用了LibGlade库的图形界面

利用LibGlade库创建图形界面并绑定到处理函数的工作已经在上个例子中同样完成了,我们没必要再重复这一细节。

在Python程序中我们定义了一些全局变量:

这个树状结构是通过Glade创建的,它的指针由如下引用获取:

exerciceTree = wTree.get_widget ("exerciceTree")

我们同样需要获取水平面板的指针,实际上,那个部件(GtkPaned,可以看成是一个容器)涉及到两个被垂直分开的水平面板,一个在左边,含有树状结构;另一个在右边,包含那些分支。现在,我们在那放置一个标签:

   paned = wTree.get_widget ("hpanedTree")
   label = GtkLabel ("No exercise selected")
   label.show ()
   paned.pack2 (label)

我们接着再来,GTK+的参考手册 (关于GtkLabelGtkPaned部件)以及Python下的源码 /usr/lib/python1.5/site-packages/gtk.py 可以帮助您理解并正确使用部件。

 

GtkTree部件

这是目前这篇文章的重点部分:如何应用GtkTree类型中的树状结构。

这个树状结构被连续的调用所围绕:addMathExercices()addFrenchExercices()addHistoryExercices()以及addGeographyExercices()函数。这些函数很相似。每个函数添加一个子类(子树)和分支(物件)的标题:

def addMathExercices ():
   subtree = addSubtree ("Mathematics")
   addExercice (subtree, "Exercise 1", "Math. Ex1")
   addExercice (subtree, "Exercise 2", "Math. Ex2")

子树(Subtree)

def addSubtree (name):
   global exerciceTree
   subTree = GtkTree ()
   item = GtkTreeItem (name)
   exerciceTree.append (item)
   item.set_subtree (subTree)
   item.show ()
   item.connect ("select", selectSubtree)
   return subTree

在一个树状结构中创建一个子树,您需要做两件事:首先,生成一个GtkTree树状结构和一个GtkTreeItem物件(及子树的标题);其次,将GtkTreeItem物件添加到根树结构(包含所有类的树)上,然后我们用set_subtree()方法在GtkTreeItem物件上添加子树,最后,将select事件绑定到GtkTreeItem物件。从而,当一个类被选中的时候,selectSubtree()函数将被调用。

GtkTreeItem

def addExercice (category, title, idValue):
   item = GtkTreeItem (title)
   item.set_data ("id", idValue)
   category.append (item)
   item.show ()
   item.connect ("select", selectTreeItem)
   item.connect ("deselect", deselectTreeItem)

这些物件使用分支的名称作为它们自己的标题,在这里,仅仅是Exercice 1Exercice 2、...每个物件我们都绑定一个 id 附加属性。GTK+可以添加一些属性到任何GtkObject类型的部件上(每个GTK+部件都是由GtkObject类型衍生来的)。实现这个过程需要两个方法,set_data (key, value)get_data (key) 去完成初始化以及获得一个属性的值,物件被添加到它的类上(子树上),物件的 show() 方法被调用以显示物件,最后,绑定上 selectdeselect 事件。当一个物件丢失选择焦点的时候,deselect 事件被激活,就在同时,deselectTreeItem() 方法被调用,然后被选中的物件的selectTreeItem() 方法将被调用。

 

处理函数

我们定义了3个处理函数:selectTreeItem()deselectTreeItem()selectSubtree()。它们使用 id 属性的值来更新文本标签(右边的)。

 

卷尾语:

我们仅仅建立了一个基本框架用于添加分支(比如许多新开发的部件)。我们主要讨论了GtkTree部件以及如何在这些部件上绑定属性。这种机制经常用于从处理函数中获取附加信息。在下个章节,您将可以尝试把改造我们曾在第一部分使用过的Couleur游戏作为Drill的一个练习。

 

附录:完整的源码

#!/usr/bin/python
# Drill - Teo Serie
# Copyright Hilaire Fernandes 2001
# Release under the terms of the GPL licence
# You can get a copy of the license at http://www.gnu.org from gtk import *
from gnome.ui import *
from GDK import *
from libglade import * exerciceTree = currentExercice = label = None

def on_about_activate(obj):
    "display the about dialog"
    about = GladeXML ("drill.glade", "about").get_widget ("about")
    about.show ()

def on_new_activate (obj):
    global exerciceTree, currentExercice

def selectTreeItem (item):
    global label
    label.set_text ("L'exercice " +
             item.get_data ("id") + "est sélectionné.")

def deselectTreeItem (item):
    global label
    label.set_text ("L'exercice " +
             item.get_data ("id") + "est désélectionné.")

def selectSubtree (subtree):
    global label
    label.set_text ("No selected exercise")

def addSubtree (name):
    global exerciceTree
    subTree = GtkTree ()
    item = GtkTreeItem (name)
    exerciceTree.append (item)
    item.set_subtree (subTree)
    item.show ()
    item.connect ("select", selectSubtree)
    return subTree

def addExercice (category, title, id):
    item = GtkTreeItem (title)
    item.set_data ("id", id)
    category.append (item)
    item.show ()
    item.connect ("select", selectTreeItem)
    item.connect ("deselect", deselectTreeItem)

def addMathExercices ():
    subtree = addSubtree ("Mathématiques")
    addExercice (subtree, "Exercice 1", "Math. Ex1")
    addExercice (subtree, "Exercice 2", "Math. Ex2")

def addFrenchExercices ():
    subtree = addSubtree ("Français")
    addExercice (subtree, "Exercice 1", "Français Ex1")
    addExercice (subtree, "Exercice 2", "Français Ex2")

def addHistoryExercices ():
    subtree = addSubtree ("Histoire")
    addExercice (subtree, "Exercice 1", "Histoire Ex1")
    addExercice (subtree, "Exercice 2", "Histoire Ex2")

def addGeographyExercices ():
    subtree = addSubtree ("Géographie")
    addExercice (subtree, "Exercice 1", "Géographie Ex1")
    addExercice (subtree, "Exercice 2", "Géographie Ex2")

def initDrill ():
    global exerciceTree, label
    wTree = GladeXML ("drill.glade", "drillApp")
    dic = {"on_about_activate": on_about_activate,
        "on_exit_activate": mainquit,
        "on_new_activate": on_new_activate}
    wTree.signal_autoconnect (dic)
    exerciceTree = wTree.get_widget ("exerciceTree")
    # Temporary until we implement real exercice
    paned = wTree.get_widget ("hpanedTree")
    label = GtkLabel ("No selected exercise")
    label.show ()
    paned.pack2 (label)
    # Free the GladeXML tree
    wTree.destroy ()
    # Add the exercices
    addMathExercices ()
    addFrenchExercices ()
    addHistoryExercices ()
    addGeographyExercices ()

initDrill ()
mainloop ()

 

对这篇文章发表评论

每篇文章都有各自的反馈页面。在这个页面里,您可以提交评论,也可以查看其他读者的评论:
 反馈页面 

主页由LinuxFocus编辑组维护
© Hilaire Fernandes, FDL
LinuxFocus.org

点击这里向LinuxFocus报告错误或提出意见
翻译信息:
fr --> -- : Hilaire Fernandes <hilaire(at)ofset.org>
fr --> de: Günther Socher <gsocher(at)web.de>
de --> en: Guido Socher <guido(at)linuxfocus.org>
en --> zh: Free Neil <freeneil(at)sohu.com>

2000-01-05, generated by lfparser version 2.23