[LinuxFocus-icon]
��ҳ  |  վ���ͼ  |  ����  |  ����

���� | �����ڿ� | ���� | ����LF
This document is available in: English  Castellano  ChineseGB  Deutsch  Francais  Italiano  Portugues  Turkce  

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

��������:

Hilaire Fernandes is the Vice-President of OFSET, an organization to promote the development of 'Free' educational software for the Gnome desktop. He also wrote Dr. Geo, a primer program for dynamic geometry, and is currently working on Dr. Genius - another education program for Gnome.


Ŀ¼:

 

Developing Applications for Gnome with Python (Part 3)

Gnome

ժҪ:

This series of articles is specially written for newbie programmers using Gnome and GNU/Linux. Python, the chosen language for development, avoids the usual overhead of compiled languages like C. The information in this article assumes a basic understanding of Python programming. More information on Python and Gnome are available at http://www.python.org and http://www.gnome.org.

Previous articles in the series :
- first article
- second article



 

���蹤�ߣ�

����������Ѿ���������Щϵ�����µ���ʼ���֡�

������Ҫ:

��ο���һ�����Ի�֪��ΰ�װ��ʹ�� Python-Gnome �� LibGlade��

 

����ģʽ

����һƪ���£��ڶ����֣��У�����Ϊ��������ϰ������һ���û����� -- Drill �����ڣ������ǽ� һ���˽������ Python ����������󿪷�������ǿ Drill �Ĺ��ܡ��ڱ��Σ��������ҷ����� Gnome �µ� Python ������

���Ǽ���ǰ�ε���ϰ����Σ����ǽ����� Drill ������һ��ɫ����Ϸ��Ϊ���ǵı��ε���ϰ�� ���ǿ���ͨ�������ϰ�˽Ȿ�ε�����ͬʱΪ��������ҵ�һ�����������

 

������󿪷�

���Ե�˵��������󿪷��ö���֮��Ĺ�ϵ���������࣬�����������Ƿ�ʵ�ʴ��ڡ� We can find comparisons in different domains like the categories of Aristotle, taxonomies, or ontologies. ��ÿһ������£���������һ��������ͨ��������������⸴�ӵ����Ρ����ǰ����ֿ���ģʽ��Ϊ������Ŀ�����

�����ֿ���ģʽ�£������ɳ�����ƣ������ɳ������dz�֮Ϊ �ࣨclasses���� ���ѳ������Ĵ�����Ϊ ʵ����instances��. ���� ���ԣ�attributes�� ����ֵ��value�� �� ������methods�� �����������塣���ڸ�����һ���࣬������˵�ĸ��ӹ�ϵ��ָ������Դӻ���̳����ԡ� ��ͨ����ϵ����֯��һ��������Ȼ����������ͬ���͡� ���dz�û�б������������Ϊ�����ࡣ ������������һ����������ȥʵ�ʶ���������������void�������dz�֮Ϊ�麯���� һ�������ຬ��һ�������麯��������޷�ʵ��������������������ͨ���ض��崿�麯�������ػ����еķ�����

��ͬ�������ڶ������ʱ����������ͬ����ͨ�����£�

  1. ����ӻ���̳����Ժͷ�����
  2. ���า�Ǵӻ���̳����ķ��������ء�
  3. ���ؼ̳У�һ�������ж�����ࡣ


 

Python ������󿪷�

�� Python �У������ֺ��٣���ʹ��������ѧϰ������󿪷��Ĺ����в��������ķ���ϸ�ڶ����ġ�

�� Python �У�һ������ķ��������麯��������ζ���������ܱ��������� -- ����������ѡ��������󿪷���ԭ�� ��������Ҳ�����﷨����ͬʱҲ�������Էֱ�һ�������Ƿ����ء� ��������޷���װ���󣬷����������󼰷����޷����ʴ˶�������Լ������� �ɴ˵ó��Ľ����ǣ��� Python �У�һ����������Զ����κζ�����˵���ǿɶ�д�ġ�

 

����

�����ǵ������У��ο� templateExercice.py���� ���ǽ��ᶨ������ exercice ���͵Ķ������ǽ��� exercice ����Ϊ�Ժ󽫴�������ϰ����һ�����ࡣ exemple ������������������������ϰ�Ļ��ࡣ��Щ��ϰ�������ཫ��exercice�������ͬ�����Ժͷ����� �⽫�������ǿ���������ϰ�����������ȥ���������ĸ������ʵ����

���磬���½�����һ�� exercice ���ʵ����

from templateExercice import exercice

monExercice = exercice ()
monExercice.activate (ceWidget)


ʵ���ϣ�����û�б�Ҫȥ���� exercice ���ʵ��������������������Լ̳е�һ��ģ����ѡ�

����

���ǿ��Ը������ǵ���Ҫ���������ԣ����磺���е�ʱ�䡣

����

Python ���룺

class exercice:
    "A template exercice"
    exerciceWidget = None
    exerciceName = "No Name"
    def __init__ (self):
        "Create the exericice widget"
    def activate (self, area):
        "Set the exercice on the area container"
        area.add (self.exerciceWidget)
    def unactivate (self, area):
        "Remove the exercice fromt the container"
        area.remove (self.exerciceWidget)
    def reset (self):
        "Reset the exercice"

��δ���������ļ� templateFichier.py �У�ʹ�����ܹ�����ÿ������ľ������á������������� exercice ��ʵ�ʵĺ����С�

���ǿ��Կ��������� area ָ���� LibGlade ������һ�� GTK+ ���� -- һ�����л���Ĵ��塣



����������У����� __init__ �� reset �����ݾ�Ϊ�գ�����б�Ҫ�������������������ǡ�

 

labelExercice��һ�� �̳� ������

�⼸����һ���յ���ϰ����ֻ��һ����--����ϰ��������ʾ�� Drill �С���������������ϰ�ĵ�һ����

������� exercice һ�������� labelExercice �������ļ� labelExercice.py �С��������ǴӶ��� exercice �̳ж����ģ� ������Ҫ���������ĸ���������ζ���ġ��ⲽ����ͨ��һ�����õ��루import������ʵ�֣�

from templateExercice import exercice

�����������˼��˵���ļ� templateExercice.py �ж������ exercice ����������ǰ�����С�

�����������һ����Ҫ��֪ʶ�㣺������ labelExercice Ϊ�� exercice �����ࡣ
labelExercice ������ķ����������

class labelExercice(exercice):

���ڣ��� labelExercice �̳����� exercice ���е����Ժͷ�����

��Ȼ���������ڻ���Щ����Ҫ�������ȣ�����Ҫ��ʼ������������ͨ������ __init__ ������ʵ�֡� ��˵�������� labelExercice �����¶���������������ʵ��������ʱ���á���Ȼ���������������exerciceWidgetָ�� ��ˣ�����û��Ҫ������ exercice �е� activate �� unactivate ������

    def __init__ (self, name):
        self.exerciceName = "Un exercice vide" (an empty exercise)
        self.exerciceWidget = GtkLabel (name)
        self.exerciceWidget.show ()

��������Ψһ�����˵ķ���������ͨ��������������������һ�� labelExercice ��ʵ����

monExercice = labelExercice ("Un exercice qui ne fait rien")
����ע��"Un exercice qui ne fait rien" ��˼�� "һ��ʲôҲ��������ϰ"��

������Ĵ�������������Ժͷ�����

# Le nom de l'exercice ����ע��exercise �����֣�
print monExercice.exerciceName

# Placer le widget de l'exercice dans le container "area"
# ����ע�������� "area" �з��ò�����
monExerice.activate (area)
 

colorExercice, �̳� �ĵڶ�������

���Ƕ���ǰ�� color game �����仯������ colorExercice ��ʵ������ ���ǰ����Ķ�������ļ� colorExercice.py �У������µ�ĩβ�����ҵ������Ĵ��롣

����仯��Ҫ�������¶���ͷֲ������������������Ǻ������Ž��������� colorExercice �С�

�����һ��ʼ��ȫ�ֱ���������Ϊ������ԣ�

class colorExercice(exercice):
    width, itemToSelect = 200, 8
    selectedItem = rootGroup = None
    # to keep trace of the canvas item
    colorShape = []

�������� labelExercice������ __init__ �������Թ��첿����

def __init__ (self):
    self.exerciceName = "Le jeu de couleur" # ����ע��ɫ����Ϸ��
    self.exerciceWidget = GnomeCanvas ()
    self.rootGroup = self.exerciceWidget.root ()
    self.buildGameArea ()
    self.exerciceWidget.set_usize (self.width,self.width)
    self.exerciceWidget.set_scroll_region (0, 0, self.width, self.width)
    self.exerciceWidget.show ()

���� exerciceWidget ָ��� GnomeCanvas �ij�ʼ������û��ʲô�仯��

��һ����Ҫ���صķ����� reset �����������������õģ���ˣ����DZ��붨������

    def reset (self):
        for item in self.colorShape:
            item.destroy ()
        del self.colorShape[0:]
        self.buildGameArea ()

ͨ��ʹ�ñ��� self ���ǿ��Է������ʵ���ķ��������ԡ�ֻ���ڷ��� buildStar �� buildShape �����⡣ ���� k ��������ֵ�滻����ע�⵽�� colorExercice.py ����һ����ֵ����� ��������ȡ��С����ֵ��ʧ�ˡ� ������⿴������ģ�� gnome.ui �� French locale ����ģ�С�����ɶ��Ŵ��棩���ҽ�����һƪ����������������⡣

 

���ĵ���

����������2�� exercise -- labelExercice �� colorExercice������ͨ������ addXXXXExercice ���������ǵ�ʵ���� ��Щʵ�����ֵ� exerciceList ��ָ��

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 addGameExercice ():
    global exerciceList
    subtree = addSubtree ("Jeux")
    addExercice (subtree, "Couleur", "Games/Color")
    exerciceList ["Games/Color"] = colorExercice ()

���� addGameExercice ͨ������ addExercice �����νṹ�д����������� id="Games/Color" ��Ҷ��㡣 ����������ֵ� exerciceList �䵱�ؼ��������� colorExercice() ������ʵ����ʹ�á�

���������������ԣ����ǿ����ڶԳ����ڲ�����֪��������ȥ������Щ��ϰ�����ǽ�����Ҫ���û��� exercice �еij��󷽷��� ���������� colorExercice ������ labelExercice �����Ų�ͬ��ʵ�֡�����Ա����ͬ�ķ�ʽȥ������ͬ����ϰ������Ӧ������ͬ�� ����ͨ�������� id ���ֵ� exerciceList ���߱��� exoSelected ������һ����ʵ�����ַ�ʽ��

def on_new_activate (obj):
    global exoSelected
    if exoSelected != None:
        exoSelected.reset ()

def selectTreeItem (item):
    global exoArea, exoSelected, exerciceList
    exoSelected = exerciceList [item.get_data ("id")]
    exoSelected.activate (exoArea)

def deselectTreeItem (item):
    global exoArea, exerciceList
    exerciceList [item.get_data ("id")].unactivate (exoArea)


[Main window of Drill]
Fig. 1 - Main window of Drill, with the color exercise

����ƪ���µĽ�β�������ܸ��ܵ��� Python �� GUI ����������󿪷���ǿ�������������ǽ�����һƪ�����м������ǵ���ϰ��

 

��¼��������Դ����

drill1.py

#!/usr/bin/python
# Drill - Teo Serie
# Copyright Hilaire Fernandes 2002
# Release under the terms of the GPL licence
# You can get a copy of the license at http://www.gnu.org


from gnome.ui import *
from libglade import *

# Import the exercice class
from colorExercice import *
from labelExercice import *

exerciceTree = currentExercice = None
# The exercice holder
exoArea = None
exoSelected = None
exerciceList = {}

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 exoSelected
    if exoSelected != None:
        exoSelected.reset ()

def selectTreeItem (item):
    global exoArea, exoSelected, exerciceList
    exoSelected = exerciceList [item.get_data ("id")]
    exoSelected.activate (exoArea)

def deselectTreeItem (item):
    global exoArea, exerciceList
    exerciceList [item.get_data ("id")].unactivate (exoArea)

def addSubtree (name):
    global exerciceTree
    subTree = GtkTree ()
    item = GtkTreeItem (name)
    exerciceTree.append (item)
    item.set_subtree (subTree)
    item.show ()
    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 addMathExercice ():
    global exerciceList
    subtree = addSubtree ("Mathématiques")
    addExercice (subtree, "Exercice 1", "Math/Ex1")
    exerciceList ["Math/Ex1"] = labelExercice ("Exercice 1")
    addExercice (subtree, "Exercice 2", "Math. Ex2")
    exerciceList ["Math/Ex2"] = labelExercice ("Exercice 2")

def addFrenchExercice ():
    global exerciceList
    subtree = addSubtree ("Français")
    addExercice (subtree, "Exercice 1", "French/Ex1")
    exerciceList ["French/Ex1"] = labelExercice ("Exercice 1")
    addExercice (subtree, "Exercice 2", "French/Ex2")
    exerciceList ["French/Ex2"] = labelExercice ("Exercice 2")

def addHistoryExercice ():
    global exerciceList
    subtree = addSubtree ("Histoire")
    addExercice (subtree, "Exercice 1", "Histoiry/Ex1")
    exerciceList ["History/Ex1"] = labelExercice ("Exercice 1")
    addExercice (subtree, "Exercice 2", "Histoiry/Ex2")
    exerciceList ["History/Ex2"] = labelExercice ("Exercice 2")

def addGeographyExercice ():
    global exerciceList
    subtree = addSubtree ("Géographie")
    addExercice (subtree, "Exercice 1", "Geography/Ex1")
    exerciceList ["Geography/Ex1"] = labelExercice ("Exercice 1")
    addExercice (subtree, "Exercice 2", "Geography/Ex2")
    exerciceList ["Geography/Ex2"] = labelExercice ("Exercice 2")

def addGameExercice ():
    global exerciceList
    subtree = addSubtree ("Jeux")
    addExercice (subtree, "Couleur", "Games/Color")
    exerciceList ["Games/Color"] = colorExercice ()


def initDrill ():
    global exerciceTree, label, exoArea
    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
    exoArea = wTree.get_widget ("exoArea")
    # Free the GladeXML tree
    wTree.destroy ()
    # Add the exercice
    addMathExercice ()
    addFrenchExercice ()
    addHistoryExercice ()
    addGeographyExercice ()
    addGameExercice ()

initDrill ()
mainloop ()


templateExercice.py

# Exercice pure virtual class
# exercice class methods should be override
# when exercice class is derived
class exercice:
    "A template exercice"
    exerciceWidget = None
    exerciceName = "No Name"
    def __init__ (self):
        "Create the exericice widget"
    def activate (self, area):
        "Set the exercice on the area container"
        area.add (self.exerciceWidget)
    def unactivate (self, area):
        "Remove the exercice fromt the container"
        area.remove (self.exerciceWidget)
    def reset (self):
        "Reset the exercice"


labelExercice.py

# Dummy Exercice - 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 templateExercice import exercice

class labelExercice(exercice):
    "A dummy exercie, it just prints a label in the exercice area"
    def __init__ (self, name):
        self.exerciceName = "Un exercice vide"
        self.exerciceWidget = GtkLabel (name)
        self.exerciceWidget.show ()


colorExercice.py

# Color Exercice - 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 math import cos, sin, pi
from whrandom import randint
from GDK import *
from gnome.ui import *

from templateExercice import exercice


# Exercice 1 : color game

class colorExercice(exercice):
    width, itemToSelect = 200, 8
    selectedItem = rootGroup = None
    # to keep trace of the canvas item
    colorShape = []
    def __init__ (self):
        self.exerciceName = "Le jeu de couleur"
        self.exerciceWidget = GnomeCanvas ()
        self.rootGroup = self.exerciceWidget.root ()
        self.buildGameArea ()
        self.exerciceWidget.set_usize (self.width,self.width)
        self.exerciceWidget.set_scroll_region (0, 0, self.width, self.width)
        self.exerciceWidget.show ()
    def reset (self):
        for item in self.colorShape:
            item.destroy ()
        del self.colorShape[0:]
        self.buildGameArea ()
    def shapeEvent (self, item, event):
        if event.type == ENTER_NOTIFY and self.selectedItem != item:
            item.set(outline_color = 'white') #highligh outline
        elif event.type == LEAVE_NOTIFY and self.selectedItem != item:
            item.set(outline_color = 'black') #unlight outline
        elif event.type == BUTTON_PRESS:
            if not self.selectedItem:
                item.set (outline_color = 'white')
                self.selectedItem = item
            elif item['fill_color_gdk'] == self.selectedItem['fill_color_gdk'] \
                 and item != self.selectedItem:
                item.destroy ()
                self.selectedItem.destroy ()
                self.colorShape.remove (item)
                self.colorShape.remove (self.selectedItem)
                self.selectedItem, self.itemToSelect = None, \
                 self.itemToSelect - 1
                if self.itemToSelect == 0:
                    self.buildGameArea ()
        return 1

    def buildShape (self,group, number, type, color):
        "build a shape of 'type' and 'color'"
        w = self.width / 4
        x, y, r = (number % 4) * w + w / 2, (number / 4) * w + w / 2, w / 2 - 2
        if type == 'circle':
            item = self.buildCircle (group, x, y, r, color)
        elif type == 'squarre':
            item = self.buildSquare (group, x, y, r, color)
        elif type == 'star':
            item = self.buildStar (group, x, y, r, 2, randint (3, 15), color)
        elif type == 'star2':
            item = self.buildStar (group, x, y, r, 3, randint (3, 15), color)
        item.connect ('event', self.shapeEvent)
        self.colorShape.append (item)

    def buildCircle (self,group, x, y, r, color):
        item = group.add ("ellipse", x1 = x - r, y1 = y - r,
                          x2 = x + r, y2 = y + r, fill_color = color,
                          outline_color = "black", width_units = 2.5)
        return item

    def buildSquare (self,group, x, y, a, color):
        item = group.add ("rect", x1 = x - a, y1 = y - a,
                          x2 = x + a, y2 = y + a, fill_color = color,
                          outline_color = "black", width_units = 2.5)
        return item

    def buildStar (self,group, x, y, r, k, n, color):
        "k: factor to get the internal radius"
        "n: number of branch"
        angleCenter = 2 * pi / n
        pts = []
        for i in range (n):
            pts.append (x + r * cos (i * angleCenter))
            pts.append (y + r * sin (i * angleCenter))
            pts.append (x + r / k * cos (i * angleCenter + angleCenter / 2))
            pts.append (y + r / k * sin (i * angleCenter + angleCenter / 2))
        pts.append (pts[0])
        pts.append (pts[1])
        item = group.add ("polygon", points = pts, fill_color = color,
                          outline_color = "black", width_units = 2.5)
        return item

    def getEmptyCell (self,l, n):
        "get the n-th non null element of l"
        length, i = len (l), 0
        while i < length:
            if l[i] == 0:
                n = n - 1
            if n < 0:
                return i
            i = i + 1
        return i

    def buildGameArea (self):
        itemColor = ['red', 'yellow', 'green', 'brown', 'blue', 'magenta',
                     'darkgreen', 'bisque1']
        itemShape = ['circle', 'squarre', 'star', 'star2']
        emptyCell = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
        self.itemToSelect, i, self.selectedItem = 8, 15, None
        for color in itemColor:
            # two items of same color
            n = 2
            while n > 0:
                cellRandom = randint (0, i)
                cellNumber = self.getEmptyCell (emptyCell, cellRandom)
                emptyCell[cellNumber] = 1
                self.buildShape (self.rootGroup, cellNumber, \
                 itemShape[randint (0, 3)], color)
                i, n = i - 1, n - 1


 

����ƪ���·�������

ÿƪ���¶��и��Եķ���ҳ�档�����ҳ����������ύ���ۣ�Ҳ���Բ鿴�������ߵ����ۣ�
 ����ҳ�� 

��ҳ��LinuxFocus�༭��ά��
© Hilaire Fernandes, FDL
LinuxFocus.org

���������LinuxFocus��������������
������Ϣ:
fr --> -- : Hilaire Fernandes <hilaire(at)ofset.org>
fr --> en: Lorne Bailey <sherm_pbody(at)yahoo.com>
en --> zh: Neil <freeneil(at)sohu.com>

2003-04-06, generated by lfparser version 2.25