Edigraph
Egy grafikus interface lépésről lépésre történő megkonstruálása

A példaprogramot Henry Garreta kurzusának website-járól vettem át a szerző szíves engedélyével.
Bevezetés a programozásba – Python nyelv 
Université de la Méditerranée – Faculté des Sciences de Luminy  

A tervezett alkalmazás:

A lépések:

A módosításokat és kiegészítéseket mindegyik lépésnél kék színnel jelzem.

0. lépés

A kiindulás: a lehető legkisebb grafikus interface-ű alkalmazás. Nyilvánvalóan semmit sem fog csinálni, de működőképes! (az egérkattintásra reagál):

from Tkinter import *

application = Tk()
application.title("Edigraph 0")

application.mainloop() 

1. lépés

Az általános térbeli elrendezés tanulmányozásához három, átmenetileg üres és színes panelt helyezünk el:

from Tkinter import *

application = Tk()
application.title("Edigraph 1")

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)                       
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)                         
                                                                                         
paneUpper = Frame(application, width=150, height = 200,                                 
            padx=4, pady=4, bd=2, relief = RIDGE)                                        
paneUpper.pack(side=TOP)                                                                
                                                                                         
paneLower = Frame(application, bg='red')                                                
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)                                     

application.mainloop() 

2. lépés

Ez a lépés csak arra szolgál, hogy ne felejtsünk a főablak aljára egy állapotsort tenni:

from Tkinter import *

application = Tk()
application.title("Edigraph 2")

statusBar = Label(application, text="Ide hamarosan help szöveg jön",                       
            bd=1, relief=SUNKEN, anchor=W)                                               
statusBar.pack(side=BOTTOM, fill=X)                                                      

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

paneLower = Frame(application, bg='red')
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

application.mainloop() 

3. lépés

Megjelenik a currentState (pillanatnyi állapot) változóval szinkronizált három rádiógomb (radiobutton): a Csúcs létrehozása, Él létrehozása, Címke definiálása

from Tkinter import *

STATE_CREATION_VERTEX = 'createVertex'
STATE_CREATION_LINE = 'createLine'
STATE_DEFINITION_ETIQUETTE = 'modifLabel'

application = Tk()
application.title("Edigraph 3")

currentState = StringVar(application)                                                     
currentState.set(STATE_CREATION_VERTEX)                                                     

statusBar = Label(application, text="Ide hamarosan help szöveg jön", 
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)                                                        
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX)                                      
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE)                                 
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE)                                 
rb.grid(row=3, sticky=W)                                                         

paneLower = Frame(application, bg='red')
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

application.mainloop() 

4. lépés

Detektáljuk a rádiógombokon történő kattintásokat, hogy frissítsük az állapotsorba kiírt szöveget :

from Tkinter import *

STATE_CREATION_VERTEX = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
STATE_DEFINITION_ETIQUETTE = 'modifLabel'

HELP_CREATION_VERTEX = "Vertex létrehozása : kattints a hely meghatározásához"      
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"           
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"

application = Tk()
application.title("Edigraph 4")

currentState = StringVar(application)
currentState.set(STATE_CREATION_VERTEX)

def checkBoxCreateVertex():
    statusBar.config(text=HELP_CREATION_VERTEX)

def checkBoxCreateLine():
    statusBar.config(text=HELP_CREATION_LINE)

def checkBoxDefEtiquette():
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)

statusBar = Label(application, text=HELP_CREATION_VERTEX,
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")
lab.grid(row=0, sticky=W)

rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)

rb.grid(row=1, sticky=W)
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)         
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                         
rb.grid(row=3, sticky=W)                                                         

paneLower = Frame(application, bg='red')
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

application.mainloop() 

5. lépés

A baloldali egérgomb kattintásainak detektálása a vásznon (canvas), felhasználása csúcsok generálására :

from Tkinter import *

STATE_CREATION_VERTEX = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
STATE_DEFINITION_ETIQUETTE = 'modifLabel' 

HELP_CREATION_VERTEX      = "Vertex létrehozása : kattints a hely meghatározásához" 
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához" 
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"

R = 3                       # rayon des sommets   a vertexek sugara                
COLOUR_VERTEX = 'black'     # couleur des sommets   a vertexek színe

application = Tk()
application.title("Edigraph 5")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX) 

def checkBoxCreateVertex():
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)                                  
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)                                      

def pressButtonLeft(event):                                                         
    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    elif currentState.get() == STATE_CREATION_LINE:                                 
        print "Az élek létrehozása még nincs implementálva"                                    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE                               
        print "Címke definiálása még nincs implementálva"                                 

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)                                                        
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

paneLower = Frame(application, bg='red')
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

application.mainloop() 

6. lépés

Az élgenerálás implementálása. Be kell vezetni egy új állapotot, ami annak a körülménynek a jellemzésére szolgál, hogy már kiválasztottuk a csúcsot, ami az élnek az egyik végpontja és hogy a következő kattintás a másik végpontot fogja definiálni.

from Tkinter import *

STATE_CREATION_VERTEX      = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'                                         
STATE_DEFINITION_ETIQUETTE = 'modifLabel'            

HELP_CREATION_VERTEX      = "Vertex létrehozása : kattints a hely meghatározásához"   
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"        
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"         
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"             

R = 3                       # rayon des sommets   a vertexek sugara                                          
COLOUR_VERTEX = 'black'     # couleur des sommets   a vertexek színe                                        

application = Tk()
application.title("Edigraph 6")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

def neighbourVertex(x, y):                                                                  
    pres = 10                                                                            
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)               
    if len(objets) > 0:    # ha van...                                              
        return objets[0]   # ...akkor az elsőt vesszük                                      
    else:                                                                                
        return None                                                                      

def createVertex(x, y):                                                                
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R,                             
                fill = COLOUR_VERTEX, width = 0)                                        

def checkBoxCreateVertex():                                                        
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)                                  
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)                                      

def centre(vertex):                                                                      
    a, b, c, d = canvas.coords(vertex)                                                  
    return (a + c) / 2, (b + d) / 2                                                      
                                                                                         
def createLine(orig, endP):                                                           
    x0, y0 = centre(orig)                                                                
    x1, y1 = centre(endP)                                                                
    line_ = canvas.create_line(x0, y0, x1, y1)                                          

def pressButtonLeft(event):                                                         
    global vertexSelected                                                            

    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    
    elif currentState.get() == STATE_CREATION_LINE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            vertexSelected = s                                                        
            currentState.set(ETAT_SUITE_CREATION_ARETE)                                   
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)                             
                                                                                         
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            createLine(vertexSelected, s)                                          
            currentState.set(STATE_CREATION_LINE)                                   
            statusBar.config(text=HELP_CREATION_LINE)                             
    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE                               
        print "Címke definiálása még nincs implementálva"                                 

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)                                         

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)                                                        
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

paneLower = Frame(application, bg='red')
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

application.mainloop()

7. lépés

A jobb egérgombbal a csúcsokra kattintva képesek leszünk áthelyezni őket. (Kellemetlen meglepetés: az élek nem követik a csúcsokat !)

from Tkinter import *

STATE_CREATION_VERTEX = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'                                         
STATE_DEFINITION_ETIQUETTE = 'modifLabel'            

HELP_CREATION_VERTEX      = "Vertex létrehozása : kattints a hely meghatározásához"   
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"        
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"         
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"             

R = 3                       # rayon des sommets   a vertexek sugara                                          
COLOUR_VERTEX = 'black'     # couleur des sommets   a vertexek színe                                        

vertexToMove = None  # (néha) a csúcsot éppen áthelyezzük                  

application = Tk()
application.title("Edigraph 7")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

def neighbourVertex(x, y):                                                                  
    pres = 10                                                                            
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)               
    if len(objets) > 0:    # ha van...                                              
        return objets[0]   # ...akkor az elsőt vesszük                                      
    else:                                                                                
        return None 

def createVertex(x, y):                                                                
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R,                             
                fill = COLOUR_VERTEX, width = 0)                                        

def checkBoxCreateVertex():                                                        
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)                                  
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)                                      

def centre(vertex):                                                                      
    a, b, c, d = canvas.coords(vertex)                                                  
    return (a + c) / 2, (b + d) / 2                                                      
                                                                                         
def createLine(orig, endP):                                                           
    x0, y0 = centre(orig)                                                                
    x1, y1 = centre(endP)                                                                
    line_ = canvas.create_line(x0, y0, x1, y1)                                          

def pressButtonLeft(event):                                                         
    global vertexSelected                                                             

    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    
    elif currentState.get() == STATE_CREATION_LINE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            vertexSelected = s                                                        
            currentState.set(ETAT_SUITE_CREATION_ARETE)                                   
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)                             
                                                                                         
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            createLine(vertexSelected, s)                                          
            currentState.set(STATE_CREATION_LINE)                                   
            statusBar.config(text=HELP_CREATION_LINE)                             
    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE                               
        print "Címke definiálása még nincs implementálva"                                 

def moveVertex(x, y):                                                             
    canvas.coords(vertexToMove, x - R, y - R, x + R, y + R)                      

def pressButtonRight(event):                                                          
    global vertexToMove                                                           
    s = neighbourVertex(event.x, event.y)                                                   
    if s != None:                                                                        
        vertexToMove = s                                                          
                                                                                         
def moveButtonRight(event):                                                         
    if vertexToMove != None:                                                      
        moveVertex(event.x, event.y)                                              
                                                                                         
def releaseButtonRight(event):                                                       
    global vertexToMove                                                           
    vertexToMove = None                                                          

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)                                         
canvas.bind('<Button-3>', pressButtonRight)                                          
canvas.bind('<B3-Motion>', moveButtonRight)                                           
canvas.bind('<ButtonRelease-3>', releaseButtonRight)                                

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)                                                        
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

paneLower = Frame(application, bg='red')
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

application.mainloop() 

8. lépés

Összekapcsoljuk a csúcsokat és az éleket annak érdekében, hogy az előbbiek elmozdulása maga után vonja az utóbbiak módosulását.

from Tkinter import *

STATE_CREATION_VERTEX      = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'                                         
STATE_DEFINITION_ETIQUETTE = 'modifLabel'            

HELP_CREATION_VERTEX      = "Vertex létrehozása : kattints a hely meghatározásához"   
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"        
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"         
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"             

R = 3                       # rayon des sommets   a vertexek sugara
COLOUR_VERTEX = 'black'     # couleur des sommets   a vertexek színe                                        

vertexToMove = None     # (néha) a csúcsot éppen áthelyezzük                  

                        # deux dictionnaires:   két szótár: 
attributs = { }         # associe a chaque sommet les aretes attenantes  összekapcsolja minegyik vertex-szel a szomszédos élet  
                        # (avec un premier élément expliqué plus tard)
endPoints = { }         # associe a chaque arete ses deux extremités    mindegyik élhez asszociálja a két végpontját                  

application = Tk()
application.title("Edigraph 8")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

def neighbourVertex(x, y):                                                                  
    pres = 10                                                                            
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)               
    if len(objets) > 0:    # ha van...                                              
        return objets[0]   # ...akkor az elsőt vesszük                                      
    else:                                                                                
        return None                                                                      

def createVertex(x, y):                                                                
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R,                             
                fill = COLOUR_VERTEX, width = 0)
    attributs[vertex] = [ "garde-place" ]                                                                                        
                                                                                         
def createLine(orig, endP):                                                           
    x0, y0 = centre(orig)                                                                
    x1, y1 = centre(endP)                                                                
    line_ = canvas.create_line(x0, y0, x1, y1) 

    endPoints[line_] = (orig, endP)                                                     
    attributs[orig].append(line_)                                                        
    attributs[endP].append(line_)                                                        

def checkBoxCreateVertex():                                                        
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)                                  
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)                                      

def centre(vertex):                                                                      
    a, b, c, d = canvas.coords(vertex)                                                  
    return (a + c) / 2, (b + d) / 2                                                      
                                             
def pressButtonLeft(event):                                                         
    global vertexSelected                                                             

    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    
    elif currentState.get() == STATE_CREATION_LINE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            vertexSelected = s                                                        
            currentState.set(ETAT_SUITE_CREATION_ARETE)                                   
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)                             
                                                                                         
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            createLine(vertexSelected, s)                                          
            currentState.set(STATE_CREATION_LINE)                                   
            statusBar.config(text=HELP_CREATION_LINE)                             
    
     else: # currentState.get() == STATE_DEFINITION_ETIQUETTE                               
        print "Címke definiálása még nincs implementálva"                                 

def replace(line_):                                                                     
    vertex0, vertex1 = endPoints[line_]                                                 
    x0, y0 = centre(vertex0)                                                             
    x1, y1 = centre(vertex1)                                                             
    canvas.coords(line_, x0, y0, x1, y1)                                                

def moveVertex(x, y):                                                                                                                 
    canvas.coords(vertexToMove, x - R, y - R, x + R, y + R)                        
    liste = attributs[vertexToMove]                                                 
    for line_ in liste[1:]:                                                                
        replace(line_)                                                                    

def pressButtonRight(event):                                                          
    global vertexToMove                                                           
    s = neighbourVertex(event.x, event.y)                                                   
    if s != None:                                                                        
        vertexToMove = s                                                          
                                                                                         
def moveButtonRight(event):                                                         
    if vertexToMove != None:                                                      
        moveVertex(event.x, event.y)                                              
                                                                                         
def releaseButtonRight(event):                                                       
    global vertexToMove                                                           
    vertexToMove = None                                                           

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)                                         
canvas.bind('<Button-3>', pressButtonRight)                                          
canvas.bind('<B3-Motion>', moveButtonRight)                                           
canvas.bind('<ButtonRelease-3>', releaseButtonRight)                                

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)                                                        
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

paneLower = Frame(application, bg='red')
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

application.mainloop()

9. lépés

Apró gadget-ek. Bevezetjük a csúcs- és élszámlálókat.

from Tkinter import *

STATE_CREATION_VERTEX      = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'                                         
STATE_DEFINITION_ETIQUETTE = 'modifLabel'            

HELP_CREATION_VERTEX      = "Vertex létrehozása : kattints a hely meghatározásához"   
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"        
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"         
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"             

R = 3                       # rayon des sommets   a vertexek sugara                                          
COLOUR_VERTEX = 'black'     # couleur des sommets   a vertexek színe                                         

vertexToMove = None  # (néha) a csúcsot éppen áthelyezzük

                                                        # deux dictionnaires:   két szótár:                                        
attributs = { }             # associe a chaque sommet les aretes attenantes  összekapcsolja minegyik vertex-szel a szomszédos élet              
                            # (avec un premier élément expliqué plus tard)               
endPoints = { }             # associe a chaque arete ses deux extremités    mindegyik élthez asszociálja a két végpontját
numberOfVertexes = 0           # A létrehozott csúcsok száma                                    
numberOfLines = 0            # A létrehozott élek száma                                     

application = Tk()
application.title("Edigraph 9")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

def neighbourVertex(x, y):                                                                  
    pres = 10                                                                            
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)               
    if len(objets) > 0:    # ha van...                                              
        return objets[0]   # ...akkor az elsőt vesszük                                      
    else:                                                                                
        return None                                                                      

def refreshCounters(nVertexes, nLines):                                              
    global numberOfVertexes, numberOfLines                                                   
                                                                                         
    numberOfVertexes = nVertexes                                                             
    numberOfLines = nLines                                                               
    etiqNbrOfVertexes.config(text = str(numberOfVertexes) + " csúcs")                        
    etiqNbrOfLines.config(text = str(numberOfLines) + " él")                           

def createVertex(x, y):                                                                
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R,                             
                fill = COLOUR_VERTEX, width = 0)
    attributs[vertex] = [ "garde-place" ]  

    refreshCounters(numberOfVertexes + 1, numberOfLines)                                                                                                                       
                                                                                         
def createLine(orig, endP):                                                           
    x0, y0 = centre(orig)                                                                
    x1, y1 = centre(endP)                                                                
    line_ = canvas.create_line(x0, y0, x1, y1) 

    endPoints[line_] = (orig, endP)                                                     
    attributs[orig].append(line_)                                                        
    attributs[endP].append(line_)                                                        

    refreshCounters(numberOfVertexes, numberOfLines + 1)                                                                                                                       

def checkBoxCreateVertex():                                                        
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)                                  
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)                                      

def centre(vertex):                                                                      
    a, b, c, d = canvas.coords(vertex)                                                  
    return (a + c) / 2, (b + d) / 2                                                      
                                             
def pressButtonLeft(event):                                                         
    global vertexSelected                                                             

    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    
    elif currentState.get() == STATE_CREATION_LINE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            vertexSelected = s                                                        
            currentState.set(ETAT_SUITE_CREATION_ARETE)                                   
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)                             
                                                                                         
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            createLine(vertexSelected, s)                                          
            currentState.set(STATE_CREATION_LINE)                                   
            statusBar.config(text=HELP_CREATION_LINE)                             
    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE                               
        print "Címke definiálása még nincs implementálva"                                 

def replace(line_):                                                                     
    vertex0, vertex1 = endPoints[line_]                                                 
    x0, y0 = centre(vertex0)                                                             
    x1, y1 = centre(vertex1)                                                             
    canvas.coords(line_, x0, y0, x1, y1)                                                

def moveVertex(x, y):                                                                                                                 
    canvas.coords(vertexToMove, x - R, y - R, x + R, y + R)                        
    liste = attributs[vertexToMove]                                                 
    for line_ in liste[1:]:                                                                
        replace(line_)                                                                    

def pressButtonRight(event):                                                          
    global vertexToMove                                                           
    s = neighbourVertex(event.x, event.y)                                                   
    if s != None:                                                                        
        vertexToMove = s                                                          
                                                                                         
def moveButtonRight(event):                                                         
    if vertexToMove != None:                                                      
        moveVertex(event.x, event.y)                                              
                                                                                         
def releaseButtonRight(event):                                                       
    global vertexToMove                                                           
    vertexToMove = None                                                           

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)                                         
canvas.bind('<Button-3>', pressButtonRight)                                          
canvas.bind('<B3-Motion>', moveButtonRight)                                           
canvas.bind('<ButtonRelease-3>', releaseButtonRight)                                

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)                                                        
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

paneLower = Frame(application, bg='red')
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

etiqNbrOfLines = Label(paneLower)                                                        
etiqNbrOfLines.pack(side=BOTTOM, anchor=W)                                                
etiqNbrOfVertexes = Label(paneLower)                                                       
etiqNbrOfVertexes.pack(side=BOTTOM, anchor=W)                                               

refreshCounters(0, 0)                                                                

application.mainloop() 

10. lépés

Hozzáadunk egy gombot, amivel minden törölhető.

from Tkinter import *
import tkMessageBox                                                                      

STATE_CREATION_VERTEX = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'                                         
STATE_DEFINITION_ETIQUETTE = 'modifLabel'            

HELP_CREATION_VERTEX = "Vertex létrehozása : kattints a hely meghatározásához"   
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"        
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"         
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"             

R = 3                       # rayon des sommets   a vertexek sugara                                          
COLOUR_VERTEX = 'black'     # couleur des sommets   a vertexek színe                                         

vertexToMove = None  # (néha) a csúcsot éppen áthelyezzük 

                            # deux dictionnaires:   két szótár:                                        
attributs = { }             # associe a chaque sommet les aretes attenantes  összekapcsolja minegyik vertex-szel a szomszédos élet              
                            # (avec un premier élément expliqué plus tard)               
endPoints = { }             # associe a chaque arete ses deux extremités    mindegyik élthez asszociálja a két végpontját                 

numberOfVertexes = 0         # A létrehozott csúcsok száma                                    
numberOfLines = 0            # A létrehozott élek száma                                     

application = Tk()
application.title("Edigraph 10")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

def neighbourVertex(x, y):                                                                  
    pres = 10                                                                            
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)               
    if len(objets) > 0:    # ha van...                                              
        return objets[0]   # ...akkor az elsőt vesszük                                      
    else:                                                                                
        return None                                                                      

def refreshCounters(nVertexes, nLines):                                              
    global numberOfVertexes, numberOfLines                                                   
                                                                                         
    numberOfVertexes = nVertexes                                                             
    numberOfLines = nLines                                                               
    etiqNbrOfVertexes.config(text = str(numberOfVertexes) + " vertex")                        
    etiqNbrOfLines.config(text = str(numberOfLines) + " él")                           

def createVertex(x, y):                                                                
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R,                             
                fill = COLOUR_VERTEX, width = 0)
    attributs[vertex] = [ "garde-place" ]  

    refreshCounters(numberOfVertexes + 1, numberOfLines)                                                                        
                                                                                         
def createLine(orig, endP):                                                           
    x0, y0 = centre(orig)                                                                
    x1, y1 = centre(endP)                                                                
    line_ = canvas.create_line(x0, y0, x1, y1) 

    endPoints[line_] = (orig, endP)                                                     
    attributs[orig].append(line_)                                                        
    attributs[endP].append(line_)                                                        

    refreshCounters(numberOfVertexes, numberOfLines + 1)                                                                                                                       

def checkBoxCreateVertex():                                                        
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)                                  
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)                                      

def centre(vertex):                                                                      
    a, b, c, d = canvas.coords(vertex)                                                  
    return (a + c) / 2, (b + d) / 2                                                      
                                             
def pressButtonLeft(event):                                                         
    global vertexSelected                                                             

    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    
    elif currentState.get() == STATE_CREATION_LINE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            vertexSelected = s                                                        
            currentState.set(ETAT_SUITE_CREATION_ARETE)                                   
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)                             
                                                                                         
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            createLine(vertexSelected, s)                                          
            currentState.set(STATE_CREATION_LINE)                                   
            statusBar.config(text=HELP_CREATION_LINE)                             
    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE                               
        print "Címke definiálása még nincs implementálva"                                 

def replace(line_):                                                                     
    vertex0, vertex1 = endPoints[line_]                                                 
    x0, y0 = centre(vertex0)                                                             
    x1, y1 = centre(vertex1)                                                             
    canvas.coords(line_, x0, y0, x1, y1)                                                

def moveVertex(x, y):                                                                                                                 
    canvas.coords(vertexToMove, x - R, y - R, x + R, y + R)                        
    liste = attributs[vertexToMove]                                                 
    for line_ in liste[1:]:                                                                
        replace(line_)                                                                    

def pressButtonRight(event):                                                          
    global vertexToMove                                                           
    s = neighbourVertex(event.x, event.y)                                                   
    if s != None:                                                                        
        vertexToMove = s                                                          
                                                                                         
def moveButtonRight(event):                                                         
    if vertexToMove != None:                                                      
        moveVertex(event.x, event.y)                                              
                                                                                         
def releaseButtonRight(event):                                                       
    global vertexToMove                                                           
    vertexToMove = None                                                           

def clearAll():                                                                       
    canvas.addtag_all("a_effacer")                                                      
    canvas.delete("a_effacer")                                                          
    refreshCounters(0, 0)                                                               

def pressButtonClear():                                                             
    if tkMessageBox.askyesno("Figyelem",                                                
            "Valóban mindent le akar rombolni?"):                                      
        clearAll()                                                                    

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)                                         
canvas.bind('<Button-3>', pressButtonRight)                                          
canvas.bind('<B3-Motion>', moveButtonRight)                                           
canvas.bind('<ButtonRelease-3>', releaseButtonRight)                                

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)                                                        
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

bouton = Button(paneUpper, text='Mindent töröl', command=pressButtonClear)          
bouton.grid(row=4) 

paneLower = Frame(application, bg='red')
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

etiqNbrOfLines = Label(paneLower)                                                        
etiqNbrOfLines.pack(side=BOTTOM, anchor=W)                                                
etiqNbrOfVertexes = Label(paneLower)                                                       
etiqNbrOfVertexes.pack(side=BOTTOM, anchor=W)                                               

refreshCounters(0, 0)

application.mainloop() 

11. lépés

Mindegyik csúcshoz hozzákapcsolunk egy címkét (kiindulásként befagyasztjuk a csúcs létrehozásakor).

from Tkinter import *
import tkMessageBox                                                                     

STATE_CREATION_VERTEX = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'                                         
STATE_DEFINITION_ETIQUETTE = 'modifLabel'            

HELP_CREATION_VERTEX      = "Vertex létrehozása : kattints a hely meghatározásához"   
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"        
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"         
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"             

R = 3                       # rayon des sommets   a vertexek sugara                                          
COLOUR_VERTEX = 'black'     # couleur des sommets   a vertexek színe                                         

vertexToMove = None  # (néha) a csúcsot éppen áthelyezzük

                            # deux dictionnaires:   két szótár:                                        
attributs = { }             # associe a chaque sommet les aretes attenantes  összekapcsolja minegyik vertex-szel a szomszédos élet              
                            # (avec un premier élément expliqué plus tard)               
endPoints = { }             # associe a chaque arete ses deux extremités    mindegyik élthez asszociálja a két végpontját                 

numberOfVertexes = 0           # A létrehozott csúcsok száma                                    
numberOfLines = 0            # A létrehozott élek száma                                     

application = Tk()
application.title("Edigraph 11")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

def neighbourVertex(x, y):                                                                  
    pres = 10                                                                            
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)               
    if len(objets) > 0:    # ha van...                                              
        return objets[0]   # ...akkor az elsőt vesszük                                      
    else:                                                                                
        return None                                                                      

def refreshCounters(nVertexes, nLines):                                              
    global numberOfVertexes, numberOfLines                                                   
                                                                                         
    numberOfVertexes = nVertexes                                                             
    numberOfLines = nLines                                                               
    etiqNbrOfVertexes.config(text = str(numberOfVertexes) + " vertex")                        
    etiqNbrOfLines.config(text = str(numberOfLines) + " él")

def createVertex(x, y):                                                                
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R,                             
                fill = COLOUR_VERTEX, width = 0)
    s = str(numberOfVertexes)                                                               
    etiquette = canvas.create_text(x + 2 * R, y - R, text = s, anchor=W)                
    attributs[vertex] = [ etiquette ]   # a placeholder helyén                       

    refreshCounters(numberOfVertexes + 1, numberOfLines)                                                                                                                       
                                                                                         
def createLine(orig, endP):                                                           
    x0, y0 = centre(orig)                                                                
    x1, y1 = centre(endP)                                                                
    line_ = canvas.create_line(x0, y0, x1, y1) 

    endPoints[line_] = (orig, endP)                                                     
    attributs[orig].append(line_)                                                        
    attributs[endP].append(line_)                                                        

    refreshCounters(numberOfVertexes, numberOfLines + 1)                                                                                                                       

def checkBoxCreateVertex():                                                        
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)                                      

def centre(vertex):                                                                      
    a, b, c, d = canvas.coords(vertex)                                                  
    return (a + c) / 2, (b + d) / 2                                                      
                                             
def pressButtonLeft(event):                                                         
    global vertexSelected                                                             

    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    
    elif currentState.get() == STATE_CREATION_LINE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            vertexSelected = s                                                        
            currentState.set(ETAT_SUITE_CREATION_ARETE)                                   
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)                             
                                                                                         
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            createLine(vertexSelected, s)                                          
            currentState.set(STATE_CREATION_LINE)                                   
            statusBar.config(text=HELP_CREATION_LINE)                             
    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE                               
        print "Címke definiálása még nincs implementálva"                                 

def replace(line_):                                                                     
    vertex0, vertex1 = endPoints[line_]                                                 
    x0, y0 = centre(vertex0)                                                             
    x1, y1 = centre(vertex1)                                                             
    canvas.coords(line_, x0, y0, x1, y1)                                                

def moveVertex(x, y):                                                                                                                 
    canvas.coords(vertexToMove, x - R, y - R, x + R, y + R)                        
    liste = attributs[vertexToMove]                                                 
    canvas.coords(liste[0], x + 2 * R, y - R)                                           
    for line_ in liste[1:]:                                                                
        replace(line_)                                                                    

def pressButtonRight(event):                                                          
    global vertexToMove                                                           
    s = neighbourVertex(event.x, event.y)                                                   
    if s != None:                                                                        
        vertexToMove = s                                                          
                                                                                         
def moveButtonRight(event):                                                         
    if vertexToMove != None:                                                      
        moveVertex(event.x, event.y)                                              
                                                                                         
def releaseButtonRight(event):                                                       
    global vertexToMove                                                           
    vertexToMove = None                                                           

def clearAll():                                                                       
    canvas.addtag_all("a_effacer")                                                      
    canvas.delete("a_effacer")                                                          
    refreshCounters(0, 0)

def pressButtonClear():                                                             
    if tkMessageBox.askyesno("Figyelem",                                                
            "Valóban mindent le akar rombolni?"):                                      
        clearAll()                                                                    

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)                                         
canvas.bind('<Button-3>', pressButtonRight)                                          
canvas.bind('<B3-Motion>', moveButtonRight)                                           
canvas.bind('<ButtonRelease-3>', releaseButtonRight)                               

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

bouton = Button(paneUpper, text='Mindent töröl', command=pressButtonClear)          
bouton.grid(row=4)                                                                       

paneLower = Frame(application, bg='red')
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

etiqNbrOfLines = Label(paneLower)                                                        
etiqNbrOfLines.pack(side=BOTTOM, anchor=W)                                                
etiqNbrOfVertexes = Label(paneLower)                                                       
etiqNbrOfVertexes.pack(side=BOTTOM, anchor=W)                                               

refreshCounters(0, 0)

application.mainloop() 

12. lépés

Itt képesek leszünk az előzőleg létrehozott csúcsok számára specifikus címkéket definiálni.

from Tkinter import *
import tkMessageBox 
import tkSimpleDialog                                                                     

STATE_CREATION_VERTEX = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'                                         
STATE_DEFINITION_ETIQUETTE = 'modifLabel'            

HELP_CREATION_VERTEX = "Vertex létrehozása : kattints a hely meghatározásához"   
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"        
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"         
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"             

R = 3                       # rayon des sommets   a vertexek sugara                                          
COLOUR_VERTEX = 'black'     # couleur des sommets   a vertexek színe

vertexToMove = None  # (néha) a csúcsot éppen áthelyezzük                   

                            # deux dictionnaires:   két szótár:                                        
attributs = { }             # associe a chaque sommet les aretes attenantes  összekapcsolja minegyik vertex-szel a szomszédos élet              
                            # (avec un premier élément expliqué plus tard)               
endPoints = { }             # associe a chaque arete ses deux extremités    mindegyik élthez asszociálja a két végpontját                 

numberOfVertexes = 0           # A létrehozott csúcsok száma                                    
numberOfLines = 0            # A létrehozott élek száma                                     

application = Tk()
application.title("Edigraph 12")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

def neighbourVertex(x, y):                                                                  
    pres = 10                                                                            
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)               
    if len(objets) > 0:    # ha van...                                              
        return objets[0]   # ...akkor az elsőt vesszük                                      
    else:                                                                                
        return None                                                                      

def refreshCounters(nVertexes, nLines):                                              
    global numberOfVertexes, numberOfLines                                                   
                                                                                         
    numberOfVertexes = nVertexes                                                             
    numberOfLines = nLines                                                               
    etiqNbrOfVertexes.config(text = str(numberOfVertexes) + " vertex")                        
    etiqNbrOfLines.config(text = str(numberOfLines) + " él")                           

def createVertex(x, y):                                                                
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R,                             
                fill = COLOUR_VERTEX, width = 0)
    s = str(numberOfVertexes)                                                               
    etiquette = canvas.create_text(x + 2 * R, y - R, text = s, anchor=W)                
    attributs[vertex] = [ etiquette ]   # a placeholder helyén'                       

    refreshCounters(numberOfVertexes + 1, numberOfLines)                                                                                                                       
                                                                                         
def createLine(orig, endP):                                                           
    x0, y0 = centre(orig)                                                                
    x1, y1 = centre(endP)                                                                
    line_ = canvas.create_line(x0, y0, x1, y1) 

    endPoints[line_] = (orig, endP)                                                     
    attributs[orig].append(line_)                                                        
    attributs[endP].append(line_)                                                        

    refreshCounters(numberOfVertexes, numberOfLines + 1)                                                                                                                       

def checkBoxCreateVertex():                                                        
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)                                   
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)                                      

def centre(vertex):                                                                      
    a, b, c, d = canvas.coords(vertex)                                                  
    return (a + c) / 2, (b + d) / 2                                                     

def definitionEtiquette(vertex):                                                         
    etiquette = attributs[vertex][0]                                                     
    texte = canvas.itemcget(etiquette, 'text')                                          
    if not texte.isdigit():                                                              
        tkMessageBox.showwarning("Címke definiálása",                                 
                "Ennek a csúcsnak a címkéjét már definiáltuk")                           
    else:                                                                                
        texte = tkSimpleDialog.askstring("Etiquette",                                    
                "Az új érték megadása :", initialvalue = texte)                     
        if texte != None:                                                                
            canvas.itemconfigure(etiquette, text = texte)                               
                                    
def pressButtonLeft(event):                                                         
    global vertexSelected                                                             

    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    
    elif currentState.get() == STATE_CREATION_LINE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            vertexSelected = s                                                        
            currentState.set(ETAT_SUITE_CREATION_ARETE)                                   
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)                             
                                                                                         
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            createLine(vertexSelected, s)                                          
            currentState.set(STATE_CREATION_LINE)                                   
            statusBar.config(text=HELP_CREATION_LINE)                             
    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            definitionEtiquette(s)                                                       

def replace(line_):                                                                     
    vertex0, vertex1 = endPoints[line_]                                                 
    x0, y0 = centre(vertex0)                                                             
    x1, y1 = centre(vertex1)                                                             
    canvas.coords(line_, x0, y0, x1, y1)                                                

def moveVertex(x, y):                                                                                                                 
    canvas.coords(vertexToMove, x - R, y - R, x + R, y + R)                        
    liste = attributs[vertexToMove]                                                 
    canvas.coords(liste[0], x + 2 * R, y - R)                                           
    for line_ in liste[1:]:                                                                
        replace(line_)

def pressButtonRight(event):                                                          
    global vertexToMove                                                           
    s = neighbourVertex(event.x, event.y)                                                   
    if s != None:                                                                        
        vertexToMove = s                                                          
                                                                                         
def moveButtonRight(event):                                                         
    if vertexToMove != None:                                                      
        moveVertex(event.x, event.y)                                              
                                                                                         
def releaseButtonRight(event):                                                       
    global vertexToMove                                                           
    vertexToMove = None                                                           

def clearAll():                                                                      
    canvas.addtag_all("a_effacer")                                                     
    canvas.delete("a_effacer")                                                         
    refreshCounters(0, 0)

def pressButtonClear():                                                            
    if tkMessageBox.askyesno("Figyelem",                                               
            "Valóban mindent le akar rombolni?"):                                      
        clearAll()                                                                    

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)                                         
canvas.bind('<Button-3>', pressButtonRight)                                          
canvas.bind('<B3-Motion>', moveButtonRight)                                           
canvas.bind('<ButtonRelease-3>', releaseButtonRight)

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

bouton = Button(paneUpper, text='Mindent töröl', command=pressButtonClear)          
bouton.grid(row=4)                                                                       

paneLower = Frame(application, bg='red')
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

etiqNbrOfLines = Label(paneLower)                                                        
etiqNbrOfLines.pack(side=BOTTOM, anchor=W)                                                
etiqNbrOfVertexes = Label(paneLower)                                                       
etiqNbrOfVertexes.pack(side=BOTTOM, anchor=W)                                               

refreshCounters(0, 0)

application.mainloop() 

13. lépés

Bevezetjük a címkék kiírására szolgáló ListBox-ot. (Azon csúcsok címkéit írja ki, melyekre átdefiniáltuk a címkéket.).

from Tkinter import *
import tkMessageBox 
import tkSimpleDialog                                                                     

STATE_CREATION_VERTEX = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'                                         
STATE_DEFINITION_ETIQUETTE = 'modifLabel'            

HELP_CREATION_VERTEX = "Vertex létrehozása : kattints a hely meghatározásához"   
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"        
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"         
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"             

R = 3                       # rayon des sommets   a vertexek sugara                                          
COLOUR_VERTEX = 'black'     # couleur des sommets   a vertexek színe                                         

vertexToMove = None  # (néha) a csúcsot éppen áthelyezzük

                            # deux dictionnaires:   két szótár:                                        
attributs = { }             # associe a chaque sommet les aretes attenantes  összekapcsolja minegyik vertex-szel a szomszédos élet              
                            # (avec un premier élément expliqué plus tard)               
endPoints = { }             # associe a chaque arete ses deux extremités    mindegyik élthez asszociálja a két végpontját                 

numberOfVertexes = 0         # A létrehozott csúcsok száma                                    
numberOfLines = 0            # A létrehozott élek száma 

application = Tk()
application.title("Edigraph 13")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

def neighbourVertex(x, y):                                                                  
    pres = 10                                                                            
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)               
    if len(objets) > 0:    # ha van...                                              
        return objets[0]   # ...akkor az elsőt vesszük                                      
    else:                                                                                
        return None                                                                      

def refreshCounters(nVertexes, nLines):                                              
    global numberOfVertexes, numberOfLines                                                   
                                                                                         
    numberOfVertexes = nVertexes                                                             
    numberOfLines = nLines                                                               
    etiqNbrOfVertexes.config(text = str(numberOfVertexes) + " vertex")                        
    etiqNbrOfLines.config(text = str(numberOfLines) + " él")

def createVertex(x, y):                                                                
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R,                             
                fill = COLOUR_VERTEX, width = 0)
    s = str(numberOfVertexes)                                                               
    etiquette = canvas.create_text(x + 2 * R, y - R, text = s, anchor=W)                
    attributs[vertex] = [ etiquette ]   # a placeholder helyén'                       

    refreshCounters(numberOfVertexes + 1, numberOfLines)                                              
                                                                                         
def createLine(orig, endP):                                                           
    x0, y0 = centre(orig)                                                                
    x1, y1 = centre(endP)                                                                
    line_ = canvas.create_line(x0, y0, x1, y1) 

    endPoints[line_] = (orig, endP)                                                     
    attributs[orig].append(line_)                                                        
    attributs[endP].append(line_)                                                        

    refreshCounters(numberOfVertexes, numberOfLines + 1)                                                                                                                       

def checkBoxCreateVertex():                                                        
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)                                  
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)

def centre(vertex):                                                                      
    a, b, c, d = canvas.coords(vertex)                                                  
    return (a + c) / 2, (b + d) / 2                                                      

def definitionEtiquette(vertex):                                                         
    etiquette = attributs[vertex][0]                                                     
    texte = canvas.itemcget(etiquette, 'text')                                          
    if not texte.isdigit():                                                              
        tkMessageBox.showwarning("Címke definiálása",                                 
                "Ennek a csúcsnak a címkéjét már definiáltuk")                           
    else:                                                                                
        texte = tkSimpleDialog.askstring("Etiquette",                                    
                "Az új érték megadása :", initialvalue = texte)                     
        if texte != None:                                                                
            canvas.itemconfigure(etiquette, text = texte)     
            listeEtiquettes.insert(END, texte)                                            
                                    
def pressButtonLeft(event):                                                         
    global vertexSelected                                                             

    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    
    elif currentState.get() == STATE_CREATION_LINE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            vertexSelected = s                                                        
            currentState.set(ETAT_SUITE_CREATION_ARETE)                                   
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)                             
                                                                                         
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            createLine(vertexSelected, s)                                          
            currentState.set(STATE_CREATION_LINE)                                   
            statusBar.config(text=HELP_CREATION_LINE) 
    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE                               
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            definitionEtiquette(s)                                                       

def replace(line_):                                                                     
    vertex0, vertex1 = endPoints[line_]                                                 
    x0, y0 = centre(vertex0)                                                             
    x1, y1 = centre(vertex1)                                                             
    canvas.coords(line_, x0, y0, x1, y1)                                                

def moveVertex(x, y):                                                                                                                 
    canvas.coords(vertexToMove, x - R, y - R, x + R, y + R)                        
    liste = attributs[vertexToMove]                                                 
    canvas.coords(liste[0], x + 2 * R, y - R)                                           
    for line_ in liste[1:]:                                                                
        replace(line_)

def pressButtonRight(event):                                                          
    global vertexToMove                                                           
    s = neighbourVertex(event.x, event.y)                                                   
    if s != None:                                                                        
        vertexToMove = s                                                          
                                                                                         
def moveButtonRight(event):                                                         
    if vertexToMove != None:                                                      
        moveVertex(event.x, event.y)                                              
                                                                                         
def releaseButtonRight(event):                                                       
    global vertexToMove                                                           
    vertexToMove = None                                                           

def clearAll():                                                                      
    canvas.addtag_all("a_effacer")                                                     
    canvas.delete("a_effacer")                                                         
    refreshCounters(0, 0)

def pressButtonClear():                                                            
    if tkMessageBox.askyesno("Figyelem",                                               
            "Valóban mindent le akar rombolni?"):                                      
        clearAll()                                                                    

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)                                         
canvas.bind('<Button-3>', pressButtonRight)                                          
canvas.bind('<B3-Motion>', moveButtonRight)                                           
canvas.bind('<ButtonRelease-3>', releaseButtonRight)

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)                                                        
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

bouton = Button(paneUpper, text='Mindent töröl', command=pressButtonClear)          
bouton.grid(row=4)

paneLower = Frame(application)                                                           
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

etiqNbrOfLines = Label(paneLower)                                                        
etiqNbrOfLines.pack(side=BOTTOM, anchor=W)                                                
etiqNbrOfVertexes = Label(paneLower)                                                       
etiqNbrOfVertexes.pack(side=BOTTOM, anchor=W)                                               

refreshCounters(0, 0)    

lab = Label(paneLower, text="Címkék :")                                              
lab.pack(side=TOP, anchor=W)                                                              
                                                            
listeEtiquettes = Listbox(paneLower)                                                     
listeEtiquettes.pack(side=BOTTOM, fill=Y, expand=True)

application.mainloop() 

14. lépés

A címkelista használata csúcsok keresésére (és nyilvánvalóvá tételére)

from Tkinter import *
import tkMessageBox 
import tkSimpleDialog                                                                     

STATE_CREATION_VERTEX = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'                                         
STATE_DEFINITION_ETIQUETTE = 'modifLabel'            

HELP_CREATION_VERTEX = "Vertex létrehozása : kattints a hely meghatározásához"   
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"        
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"         
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"             

R = 3                       # rayon des sommets   a vertexek sugara
R2 = 6                      # a vertexek sugara nyilvánvalóvá téve                           
COLOUR_VERTEX = 'black'     # couleur des sommets   a vertexek színe
COLOUR_VERTEX2 = 'red'     # couleur des sommets mis en evidence   a vertexek színe  nyilvánvalóvá téve                          

vertexToMove = None  # (néha) a csúcsot éppen áthelyezzük

                            # trois dictionnaires:   három szótár:                                        
attributs = { }             # associe a chaque sommet les aretes attenantes  összekapcsolja minegyik vertex-szel a szomszédos élet              
                            # (egy késobbiekben magyarázott első elemmel)               
endPoints = { }             # associe a chaque arete ses deux extremités    mindegyik élthez asszociálja a két végpontját  
                
vertexAssociated = { }         # associe a chaque étiquette le sommet correspondant     minden címókéhez a megfelelő csúcshoz kapcsolja

numberOfVertexes = 0         # A létrehozott csúcsok száma                                    
numberOfLines = 0            # A létrehozott élek száma

application = Tk()
application.title("Edigraph 14")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

def neighbourVertex(x, y):                                                                  
    pres = 10                                                                            
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)               
    if len(objets) > 0:    # ha van...                                              
        return objets[0]   # ...akkor az elsőt vesszük                                      
    else:                                                                                
        return None                                                                      

def refreshCounters(nVertexes, nLines):                                              
    global numberOfVertexes, numberOfLines                                                   
                                                                                         
    numberOfVertexes = nVertexes                                                             
    numberOfLines = nLines                                                               
    etiqNbrOfVertexes.config(text = str(numberOfVertexes) + " vertex")                        
    etiqNbrOfLines.config(text = str(numberOfLines) + " él")

def createVertex(x, y):                                                                
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R,                             
                fill = COLOUR_VERTEX, width = 0)
    s = str(numberOfVertexes)                                                               
    etiquette = canvas.create_text(x + 2 * R, y - R, text = s, anchor=W)                
    attributs[vertex] = [ etiquette ]   # a placeholder helyén                       

    refreshCounters(numberOfVertexes + 1, numberOfLines)
                                                                                         
def createLine(orig, endP):                                                           
    x0, y0 = centre(orig)                                                                
    x1, y1 = centre(endP)                                                                
    line_ = canvas.create_line(x0, y0, x1, y1) 

    endPoints[line_] = (orig, endP)                                                     
    attributs[orig].append(line_)                                                        
    attributs[endP].append(line_)                                                        

    refreshCounters(numberOfVertexes, numberOfLines + 1)                                                                                                                       

def checkBoxCreateVertex():                                                        
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)                                      

def centre(vertex):                                                                      
    a, b, c, d = canvas.coords(vertex)                                                  
    return (a + c) / 2, (b + d) / 2

def definitionEtiquette(vertex):                                                         
    etiquette = attributs[vertex][0]                                                     
    texte = canvas.itemcget(etiquette, 'text')                                          
    if not texte.isdigit():                                                              
        tkMessageBox.showwarning("Címke definiálása",                                 
                "Ennek a csúcsnak a címkéjét már definiáltuk")                           
    else:                                                                                
        texte = tkSimpleDialog.askstring("Etiquette",                                    
                "Az új érték megadása :", initialvalue = texte)                     
        if texte != None:                                                                
            canvas.itemconfigure(etiquette, text = texte)     
            listeEtiquettes.insert(END, texte)
            vertexAssociated[texte] = vertex                                                                                             
                                    
def pressButtonLeft(event):                                                         
    global vertexSelected                                                             

    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    
    elif currentState.get() == STATE_CREATION_LINE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            vertexSelected = s                                                        
            currentState.set(ETAT_SUITE_CREATION_ARETE)                                   
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)                             
                                                                                         
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            createLine(vertexSelected, s)                                          
            currentState.set(STATE_CREATION_LINE)                                   
            statusBar.config(text=HELP_CREATION_LINE)                             
    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE                               
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            definitionEtiquette(s)                                                       

def replace(line_):                                                                     
    vertex0, vertex1 = endPoints[line_]                                                 
    x0, y0 = centre(vertex0)                                                             
    x1, y1 = centre(vertex1)                                                             
    canvas.coords(line_, x0, y0, x1, y1)                                                

def moveVertex(x, y):                                                                                                                 
    canvas.coords(vertexToMove, x - R, y - R, x + R, y + R)                        
    liste = attributs[vertexToMove]                                                 
    canvas.coords(liste[0], x + 2 * R, y - R)                                           
    for line_ in liste[1:]:                                                                
        replace(line_)

def pressButtonRight(event):                                                          
    global vertexToMove                                                           
    s = neighbourVertex(event.x, event.y)                                                   
    if s != None:                                                                        
        vertexToMove = s                                                          
                                                                                         
def moveButtonRight(event):                                                         
    if vertexToMove != None:                                                      
        moveVertex(event.x, event.y)                                              
                                                                                         
def releaseButtonRight(event):                                                       
    global vertexToMove                                                           
    vertexToMove = None                                                           

def clearAll():                                                                      
    canvas.addtag_all("a_effacer")                                                     
    canvas.delete("a_effacer")                                                         
    refreshCounters(0, 0)                                                              

def pressButtonClear():                                                            
    if tkMessageBox.askyesno("Figyelem",                                               
            "Valóban mindent le akar rombolni?"):                                      
        clearAll()

def actionOnList(evt):                                                                  
    selections = listeEtiquettes.curselection()  # ex.: ('3', '5', '9')                   
    selection = selections[0]                    # ex.: '3'                               
    i = int(selection)                           # ex.: 3                                 
    texte = listeEtiquettes.get(i)               # le texte correspondant        a megfelelő szöveg                 
    vertex = vertexAssociated[texte]                # le sommet correspondant       a megfelelő csúcs        
                                                                                          
    x, y = centre(vertex)                                                                 
    if canvas.itemcget(vertex, 'fill') == COLOUR_VERTEX:                                
        canvas.itemconfigure(vertex, fill=COLOUR_VERTEX2)                               
        canvas.coords(vertex, x - R2, y - R2, x + R2, y + R2)                            
    else:                                                                                 
        canvas.itemconfigure(vertex, fill=COLOUR_VERTEX)                                
        canvas.coords(vertex, x - R, y - R, x + R, y + R)                                

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)                                         
canvas.bind('<Button-3>', pressButtonRight)                                          
canvas.bind('<B3-Motion>', moveButtonRight)                                           
canvas.bind('<ButtonRelease-3>', releaseButtonRight)                                

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)

rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

bouton = Button(paneUpper, text='Mindent töröl', command=pressButtonClear)          
bouton.grid(row=4)                                                                       

paneLower = Frame(application)                                                           
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

etiqNbrOfLines = Label(paneLower)                                                        
etiqNbrOfLines.pack(side=BOTTOM, anchor=W)                                                
etiqNbrOfVertexes = Label(paneLower)                                                       
etiqNbrOfVertexes.pack(side=BOTTOM, anchor=W)

refreshCounters(0, 0)    

lab = Label(paneLower, text="Címkék :")                                              
lab.pack(side=TOP, anchor=W)                                                              
                                                            
listeEtiquettes = Listbox(paneLower)                                                     
listeEtiquettes.pack(side=BOTTOM, fill=Y, expand=True)

refreshCounters(0, 0)    

listeEtiquettes.bind('<Button-1>', actionOnList)

application.mainloop() 

15. lépés

Megjelennek a menük.

from Tkinter import *
import tkMessageBox 
import tkSimpleDialog                                                                     
import sys                                                                                

STATE_CREATION_VERTEX  = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'                                         
STATE_DEFINITION_ETIQUETTE = 'modifLabel'            

HELP_CREATION_VERTEX = "Vertex létrehozása : kattints a hely meghatározásához"   
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"        
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"         
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"             

R = 3                       # rayon des sommets   a vertexek sugara                                          
R2 = 6                      # rayon des sommets mis en évidence                           
COLOUR_VERTEX = 'black'    # couleur des sommets   a vertexek színe                                         
COLOUR_VERTEX2 = 'red'     # couleur des sommets mis en évidence  a vertexek színe nyilvánvalóvá téve                                                                

vertexToMove = None  # (néha) a csúcsot éppen áthelyezzük

                            # trois dictionnaires:   három szótár:                                        
attributs = { }             # associe a chaque sommet les aretes attenantes  összekapcsolja minegyik vertex-szel a szomszédos élet              
                            # (avec un premier élément expliqué plus tard)               
endPoints = { }             # associe a chaque arete ses deux extremités    mindegyik élthez asszociálja a két végpontját 
                
vertexAssociated = { }         # associe a chaque étiquette le sommet correspondant     minden címókéhez a megfelelő csúcshoz kapcsolja          

numberOfVertexes = 0           # A létrehozott csúcsok száma                                    
numberOfLines = 0            # A létrehozott élek száma                                     

application = Tk()
application.title("Edigraph 15")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

def neighbourVertex(x, y):                                                                  
    pres = 10                                                                            
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)               
    if len(objets) > 0:    # ha van...                                              
        return objets[0]   # ...akkor az elsőt vesszük                                      
    else:                                                                                
        return None                                                                      

def refreshCounters(nVertexes, nLines):                                              
    global numberOfVertexes, numberOfLines                                                   
                                                                                         
    numberOfVertexes = nVertexes                                                             
    numberOfLines = nLines                                                               
    etiqNbrOfVertexes.config(text = str(numberOfVertexes) + " vertex")                        
    etiqNbrOfLines.config(text = str(numberOfLines) + " él")

def createVertex(x, y):                                                                
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R,                             
                fill = COLOUR_VERTEX, width = 0)
    s = str(numberOfVertexes)                                                               
    etiquette = canvas.create_text(x + 2 * R, y - R, text = s, anchor=W)                
    attributs[vertex] = [ etiquette ]   # a placeholder helyén                       

    refreshCounters(numberOfVertexes + 1, numberOfLines)                                                                                                                       
                                                                                         
def createLine(orig, endP):                                                           
    x0, y0 = centre(orig)                                                                
    x1, y1 = centre(endP)                                                                
    line_ = canvas.create_line(x0, y0, x1, y1) 

    endPoints[line_] = (orig, endP)                                                     
    attributs[orig].append(line_)                                                        
    attributs[endP].append(line_)                                                        

    refreshCounters(numberOfVertexes, numberOfLines + 1)                                                                   

def checkBoxCreateVertex():                                                        
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)                                  
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)                                      

def centre(vertex):                                                                      
    a, b, c, d = canvas.coords(vertex)                                                  
    return (a + c) / 2, (b + d) / 2                                                      

def definitionEtiquette(vertex):                                                         
    etiquette = attributs[vertex][0]                                                     
    texte = canvas.itemcget(etiquette, 'text')                                          
    if not texte.isdigit():                                                              
        tkMessageBox.showwarning("Címke definiálása",                                 
                "Ennek a csúcsnak a címkéjét már definiáltuk")
    else:                                                                                
        texte = tkSimpleDialog.askstring("Etiquette",                                    
                "Az új érték megadása :", initialvalue = texte)                     
        if texte != None:                                                                
            canvas.itemconfigure(etiquette, text = texte)     
            listeEtiquettes.insert(END, texte)
            vertexAssociated[texte] = vertex                          

                                    
def pressButtonLeft(event):                                                         
    global vertexSelected                                                             

    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    
    elif currentState.get() == STATE_CREATION_LINE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            vertexSelected = s                                                        
            currentState.set(ETAT_SUITE_CREATION_ARETE)                                   
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)                             
                                                                                         
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            createLine(vertexSelected, s)                                          
            currentState.set(STATE_CREATION_LINE)                                   
            statusBar.config(text=HELP_CREATION_LINE) 
    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE                               
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            definitionEtiquette(s)                                                       

def replace(line_):                                                                     
    vertex0, vertex1 = endPoints[line_]                                                 
    x0, y0 = centre(vertex0)                                                             
    x1, y1 = centre(vertex1)                                                             
    canvas.coords(line_, x0, y0, x1, y1)                                                

def moveVertex(x, y):                                                                                                                 
    canvas.coords(vertexToMove, x - R, y - R, x + R, y + R)                        
    liste = attributs[vertexToMove]                                                 
    canvas.coords(liste[0], x + 2 * R, y - R)                                           
    for line_ in liste[1:]:                                                                
        replace(line_)

def pressButtonRight(event):                                                          
    global vertexToMove                                                           
    s = neighbourVertex(event.x, event.y)                                                   
    if s != None:                                                                        
        vertexToMove = s                                                          
                                                                                         
def moveButtonRight(event):                                                         
    if vertexToMove != None:                                                      
        moveVertex(event.x, event.y)                                              
                                                                                         
def releaseButtonRight(event):                                                       
    global vertexToMove                                                           
    vertexToMove = None                                                           

def clearAll():                                                                      
    canvas.addtag_all("a_effacer")                                                     
    canvas.delete("a_effacer")                                                         
    refreshCounters(0, 0)

def pressButtonClear():                                                            
    if tkMessageBox.askyesno("Figyelem",                                               
            "Valóban mindent le akar rombolni?"):                                      
        clearAll()    

def actionOnList(evt):                                                                  
    selections = listeEtiquettes.curselection()  # ex.: ('3', '5', '9')                   
    selection = selections[0]                    # ex.: '3'                               
    i = int(selection)                           # ex.: 3                                 
    texte = listeEtiquettes.get(i)               # le texte correspondant        a megfelelő szöveg
    vertex = vertexAssociated[texte]                # le sommet correspondant       a megfelelő csúcs 
                                                                                          
    x, y = centre(vertex)                                                                 
    if canvas.itemcget(vertex, 'fill') == COLOUR_VERTEX:                                
        canvas.itemconfigure(vertex, fill=COLOUR_VERTEX2)                               
        canvas.coords(vertex, x - R2, y - R2, x + R2, y + R2)                            
    else:                                                                                 
        canvas.itemconfigure(vertex, fill=COLOUR_VERTEX)                                
        canvas.coords(vertex, x - R, y - R, x + R, y + R)

def comMenuQuitter():                                                                     
    if tkMessageBox.askyesno("Figyelem",                                                 
            "Valóban ki akar lépni a programból ?"):                                
        sys.exit(0)                                                                       
                                                                                          
def comMenuAPropos():                                                                     
    tkMessageBox.showinfo(                                                                
            "About...",                                                             
            "Az Edigraph\n\n" +                                                              
            "egy tisztán demonstratív célú gráfszerkesztő\n" +                             
            "a grafikus interface Tkinterrel való megvalósításának bemutatására    \n\n"  +         
            "(C) H. Garreta, 2005")                                                       
                                                                                          
def saveGraph():                                                                   
    tkMessageBox.showwarning("Bocsámat...",                                                
            "A gráf mentése funkció még nincs implementálva")              
                                                                                          
def restoreGraph():                                                                    
    tkMessageBox.showwarning("Bocsánat...",                                                
            "A gráf visszaállítása funkció még nincs implementálva")                

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)                                         
canvas.bind('<Button-3>', pressButtonRight)                                          
canvas.bind('<B3-Motion>', moveButtonRight)                                           
canvas.bind('<ButtonRelease-3>', releaseButtonRight)                                

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

bouton = Button(paneUpper, text='Mindent töröl', command=pressButtonClear)          
bouton.grid(row=4)                                                                       

paneLower = Frame(application)                                                           
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

etiqNbrOfLines = Label(paneLower)                                                        
etiqNbrOfLines.pack(side=BOTTOM, anchor=W)                                                
etiqNbrOfVertexes = Label(paneLower)                                                       
etiqNbrOfVertexes.pack(side=BOTTOM, anchor=W)                                               

refreshCounters(0, 0)    

lab = Label(paneLower, text="Címkék :")                                              
lab.pack(side=TOP, anchor=W)                                                              
                                                            
listeEtiquettes = Listbox(paneLower)                                                     
listeEtiquettes.pack(side=BOTTOM, fill=Y, expand=True)                                    
listeEtiquettes.bind('<Button-1>', actionOnList)

menuBar = Menu(application)                                                          
application.config(menu = menuBar)                                                   
                                                                                          
saveGraph = Menu(menuBar)                                                          
menuBar.add_cascade(label="File", menu=saveGraph)                               
                                                                                          
saveGraph.add_command(label="Új", command=pressButtonClear)                   
saveGraph.add_command(label="Megnyitás...", command=restoreGraph)                       
saveGraph.add_command(label="Mentés, mint...", command=saveGraph)            
saveGraph.add_separator()                                                               
saveGraph.add_command(label="Kilépés", command=comMenuQuitter)                          
                                                                                          
menuHelp = Menu(menuBar)                                                             
menuBar.add_cascade(label="Help", menu=menuHelp)                                     
                                                                                          
menuHelp.add_command(label="A propos", command=comMenuAPropos)                            

application.mainloop() 

16. lépés

A gráf mentése egy szövegfile-ba.

from Tkinter import *
import tkMessageBox 
import tkSimpleDialog                                                                     
import tkFileDialog                                                                       
import sys

STATE_CREATION_VERTEX = 'createVertex'
STATE_CREATION_LINE = 'createLine' 
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'                                         
STATE_DEFINITION_ETIQUETTE = 'modifLabel'            

HELP_CREATION_VERTEX = "Vertex létrehozása : kattints a hely meghatározásához"   
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"        
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"         
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"             

R = 3                       # rayon des sommets   a vertexek sugara                                          
R2 = 6                      # rayon des sommets mis en évidence   a vertexek sugara nyilvánvalóvá téve                        
COLOUR_VERTEX = 'black'    # couleur des sommets   a vertexek színe                                         
COLOUR_VERTEX2 = 'red'     # couleur des sommets mis en évidence   a vertexek színe nyilvánvalóvá téve 


vertexToMove = None  # (néha) a csúcsot éppen áthelyezzük                   

                            # trois dictionnaires:   három szótár:                                        
attributs = { }             # associe a chaque sommet les aretes attenantes  összekapcsolja minegyik vertex-szel a szomszédos élet              
                            # (avec un premier élément expliqué plus tard)               
endPoints = { }             # associe a chaque arete ses deux extremités    mindegyik élthez asszociálja a két végpontját 
                
vertexAssociated = { }         # associe a chaque étiquette le sommet correspondant     minden címókéhez a megfelelő csúcshoz kapcsolja          

numberOfVertexes = 0           # A létrehozott csúcsok száma                                    
numberOfLines = 0              # A létrehozott élek száma

application = Tk()
application.title("Edigraph 16")

currentState = StringVar(application)              
currentState.set(STATE_CREATION_VERTEX)

def neighbourVertex(x, y):                                                                  
    pres = 10                                                                            
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)               
    if len(objets) > 0:    # ha van...                                              
        return objets[0]   # ...akkor az elsőt vesszük                                      
    else:                                                                                
        return None                                                                      

def refreshCounters(nVertexes, nLines):                                              
    global numberOfVertexes, numberOfLines                                                   
                                                                                         
    numberOfVertexes = nVertexes                                                             
    numberOfLines = nLines                                                               
    etiqNbrOfVertexes.config(text = str(numberOfVertexes) + " vertex")                        
    etiqNbrOfLines.config(text = str(numberOfLines) + " él")

def createVertex(x, y):                                                                
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R,                             
                fill = COLOUR_VERTEX, width = 0)
    s = str(numberOfVertexes)                                                               
    etiquette = canvas.create_text(x + 2 * R, y - R, text = s, anchor=W)                
    attributs[vertex] = [ etiquette ]   # a placeholder helyén'                       

    refreshCounters(numberOfVertexes + 1, numberOfLines)                                                                                                                       
                                                                                         
def createLine(orig, endP):                                                           
    x0, y0 = centre(orig)                                                                
    x1, y1 = centre(endP)                                                                
    line_ = canvas.create_line(x0, y0, x1, y1) 

    endPoints[line_] = (orig, endP)                                                     
    attributs[orig].append(line_)                                                        
    attributs[endP].append(line_)                                                        

    refreshCounters(numberOfVertexes, numberOfLines + 1)                                                                   

def checkBoxCreateVertex():                                                        
    statusBar.config(text=HELP_CREATION_VERTEX)                                       
                                                                                      
def checkBoxCreateLine():                                                         
    statusBar.config(text=HELP_CREATION_LINE)                                  
                                                                                      
def checkBoxDefEtiquette():                                                          
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)                                      

def centre(vertex):                                                                      
    a, b, c, d = canvas.coords(vertex)                                                  
    return (a + c) / 2, (b + d) / 2                                                      

def definitionEtiquette(vertex):                                                         
    etiquette = attributs[vertex][0]                                                     
    texte = canvas.itemcget(etiquette, 'text')                                          
    if not texte.isdigit():                                                              
        tkMessageBox.showwarning("Címke definiálása",                                 
                "Ennek a csúcsnak a címkéjét már definiáltuk")
    else:                                                                                
        texte = tkSimpleDialog.askstring("Etiquette",                                    
                "Az új érték megadása :", initialvalue = texte)                     
        if texte != None:                                                                
            canvas.itemconfigure(etiquette, text = texte)     
            listeEtiquettes.insert(END, texte)
            vertexAssociated[texte] = vertex
                                    
def pressButtonLeft(event):                                                         
    global vertexSelected                                                             

    if currentState.get() == STATE_CREATION_VERTEX:                                        
        createVertex(event.x, event.y)                                                 
    
    elif currentState.get() == STATE_CREATION_LINE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            vertexSelected = s                                                        
            currentState.set(ETAT_SUITE_CREATION_ARETE)                                   
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)                             
                                                                                         
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:                                 
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            createLine(vertexSelected, s)                                          
            currentState.set(STATE_CREATION_LINE)                                   
            statusBar.config(text=HELP_CREATION_LINE)                             
    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE                               
        s = neighbourVertex(event.x, event.y)                                               
        if s != None:                                                                    
            definitionEtiquette(s)                                                       

def replace(line_):                                                                     
    vertex0, vertex1 = endPoints[line_]                                                 
    x0, y0 = centre(vertex0)                                                             
    x1, y1 = centre(vertex1)                                                             
    canvas.coords(line_, x0, y0, x1, y1)                                                

def moveVertex(x, y):                                                                                                                 
    canvas.coords(vertexToMove, x - R, y - R, x + R, y + R)                        
    liste = attributs[vertexToMove]                                                 
    canvas.coords(liste[0], x + 2 * R, y - R)                                           
    for line_ in liste[1:]:                                                                
        replace(line_)

def pressButtonRight(event):                                                          
    global vertexToMove                                                           
    s = neighbourVertex(event.x, event.y)                                                   
    if s != None:                                                                        
        vertexToMove = s                                                          
                                                                                         
def moveButtonRight(event):                                                         
    if vertexToMove != None:                                                      
        moveVertex(event.x, event.y)                                              
                                                                                         
def releaseButtonRight(event):                                                       
    global vertexToMove                                                           
    vertexToMove = None                                                           

def clearAll():                                                                      
    canvas.addtag_all("a_effacer")                                                     
    canvas.delete("a_effacer")                                                         
    refreshCounters(0, 0)

def pressButtonClear():                                                            
    if tkMessageBox.askyesno("Figyelem",                                               
            "Valóban mindent le akar rombolni?"):                                      
        clearAll()    

def actionOnList(evt):                                                                  
    selections = listeEtiquettes.curselection()  # ex.: ('3', '5', '9')                   
    selection = selections[0]                    # ex.: '3'                               
    i = int(selection)                           # ex.: 3                                 
    texte = listeEtiquettes.get(i)               # le texte correspondant        a megfelelő szöveg                 
    vertex = vertexAssociated[texte]                # le sommet correspondant       a megfelelő csúcs
                                                                                          
    x, y = centre(vertex)                                                                 
    if canvas.itemcget(vertex, 'fill') == COLOUR_VERTEX:                                
        canvas.itemconfigure(vertex, fill=COLOUR_VERTEX2)                               
        canvas.coords(vertex, x - R2, y - R2, x + R2, y + R2)                            
    else:                                                                                 
        canvas.itemconfigure(vertex, fill=COLOUR_VERTEX)                                
        canvas.coords(vertex, x - R, y - R, x + R, y + R)                                

def comMenuQuitter():                                                                     
    if tkMessageBox.askyesno("Figyelem",                                                 
            "Valóban ki akar lépni a programból ?"):                                
        sys.exit(0)                                                                       
                                                                                          
def comMenuAPropos():                                                                     
    tkMessageBox.showinfo(                                                                
            "About...",                                                             
            "Az Edigraph\n\n" +                                                              
            "egy tisztán demonstratív célú gráfszerkesztő\n" +                             
            "a grafikus interface Tkinterrel való megvalósításának bemutatására    \n\n"  +         
            "(C) H. Garreta, 2005")
                                                                                          
def saveGraph():                                                                                                                                  
    file = tkFileDialog.asksaveasfile()                                                
    if file == None:                                                                   
        return                                                                            
                                                                                          
    liste = canvas.find_all()                                                            
    for item in liste:                                                                    
        if canvas.type(item) == 'oval':                                                  
            dep = attributs[item]                                                         
            print >> file, '"' + canvas.itemcget(dep[0], 'text') + '"',               
            print >> file, centre(item),                                               
            for line_ in dep[1:]:                                                         
                neighbour = endPoints[line_][0]                                             
                if neighbour == item:                                                        
                    neighbour = endPoints[line_][1]                                         
                s = canvas.itemcget(attributs[neighbour][0], 'text')                        
                print >> file, '"' + s + '"',                                          
            print >> file                                                              
                                                                                          
    file.close()
                                                                                          
def restoreGraph():                                                                    
    tkMessageBox.showwarning("Bocsánat...",                                                
            "A gráf visszaállítása funkció még nincs implementálva")                

statusBar = Label(application, text=HELP_CREATION_VERTEX,                             
            bd=1, relief=SUNKEN, anchor=W)     
statusBar.pack(side=BOTTOM, fill=X)    

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)                                         
canvas.bind('<Button-3>', pressButtonRight)                                          
canvas.bind('<B3-Motion>', moveButtonRight)                                           
canvas.bind('<ButtonRelease-3>', releaseButtonRight)                                

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")                                  
lab.grid(row=0, sticky=W)                                                        
                                                                                 
rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása',       
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)                                              
rb.grid(row=1, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása',        
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)      
rb.grid(row=2, sticky=W)                                                         
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása',  
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)                                      
rb.grid(row=3, sticky=W)                                                         

bouton = Button(paneUpper, text='Mindent töröl', command=pressButtonClear)          
bouton.grid(row=4)                                                                       

paneLower = Frame(application)                                                           
paneLower.pack(side=BOTTOM, fill=BOTH, expand=True)

etiqNbrOfLines = Label(paneLower)                                                        
etiqNbrOfLines.pack(side=BOTTOM, anchor=W)                                                
etiqNbrOfVertexes = Label(paneLower)                                                       
etiqNbrOfVertexes.pack(side=BOTTOM, anchor=W)                                               

refreshCounters(0, 0)    

lab = Label(paneLower, text="Címkék :")                                              
lab.pack(side=TOP, anchor=W)                                                              
                                                            
listeEtiquettes = Listbox(paneLower)                                                     
listeEtiquettes.pack(side=BOTTOM, fill=Y, expand=True)                                    
listeEtiquettes.bind('<Button-1>', actionOnList)                                 

menuBar = Menu(application)                                                          
application.config(menu = menuBar)                                                   
                                                                                          
menuFile = Menu(menuBar)                                                          
menuBar.add_cascade(label="File", menu=menuFile)
                                                                                          
menuFile.add_command(label="Új", command=pressButtonClear)                   
menuFile.add_command(label="Megnyitás...", command=restoreGraph)                       
menuFile.add_command(label="Mentés, mint...", command=saveGraph)            
menuFile.add_separator()                                                               
menuFile.add_command(label="Kilépés", command=comMenuQuitter)                          
                                                                                          
menuHelp = Menu(menuBar)                                                             
menuBar.add_cascade(label="Help", menu=menuHelp)                                     
                                                                                          
menuHelp.add_command(label="A propos", command=comMenuAPropos)

application.mainloop() 

Végső állapot

Majdnem ugyanaz, mint az előző, azonban a függvények máshogy vannak elrendezve.

from Tkinter import *
import tkMessageBox
import tkSimpleDialog
import tkFileDialog
import sys


### CONSTANTES ##################################################################

### a rendszer állapota azt definiálja, hogy mi lesz a következő kattintás hatása

STATE_CREATION_VERTEX      = 'createVertex'
STATE_CREATION_LINE = 'createLine'
ETAT_SUITE_CREATION_ARETE = 'suiteCreationArete'
STATE_DEFINITION_ETIQUETTE = 'modifLabel'

### az állapotsorba kiírt szöveg (az ablak aljára)

HELP_CREATION_VERTEX      = "Vertex létrehozása : kattints a hely meghatározásához"
HELP_CREATION_LINE = "Él létrehozása : kattints a kezdőpont definiálásához"
AIDE_SUITE_CREATION_ARETE = "Él létrehozása : kattints a végpontok definiálásához"
HELP__DEFINITION_ETIQUETTE = "Címke definiálása : jelölje meg a csúcsot"

### a csúcsokkal kapcsolatos konstansok

R = 3                       # rayon des sommets   a vertexek sugara
R2 = 2 * R                  # rayon des sommets mis en évidence
COLOUR_VERTEX = 'black'    # couleur des sommets   a vertexek színe 
COLOUR_VERTEX2 = 'red'     # couleur des sommets   a vertexek színe  mis en évidence


### GLOBÁLIS VÁLTOZÓK ###########################################################
                            
attributs = { }             # mindegyik csúcshoz asszociálja a címkéjét és a szomszédos éleket
endPoints = { }             # mindegyik élthez asszociálja a két végpontját
vertexAssociated = { }         # egy címkéhez asszociálja a megfelelő csúcsot correspondant

numberOfVertexes = 0           # A létrehozott csúcsok száma
numberOfLines = 0              # A létrehozott élek száma
vertexToMove = None         # bizonyos pillanatokban: az áthelyezés közben lévő vertex
vertexSelected = None       # egy előző akcióban (esetleg) kiválasztott vertex
                         


### KÜLÖNBÖZŐ FÜGGVÉNYEK ##########################################################

def refreshCounters(nVertexes, nLines):
    """ A jelzett értékeket adja a numberOfVertexes és numberOfLines
        számlálóknak és aktualizálja a kiírást """
    global numberOfVertexes, numberOfLines
    
    numberOfVertexes = nVertexes
    numberOfLines = nLines
    etiqNbrOfVertexes.config(text = str(numberOfVertexes) + " vertex")
    etiqNbrOfLines.config(text = str(numberOfLines) + " él")    

def createVertex(x, y):
    """Az (x, y) középpontú és R sugarú körrel reprezentált csúcs létrehozása
 """
    vertex = canvas.create_oval(x - R, y - R, x + R, y + R, 
                fill = COLOUR_VERTEX, width = 0)
    s = str(numberOfVertexes)
    etiquette = canvas.create_text(x + 2 * R, y - R, text = s, anchor=W)
    attributs[vertex] = [ etiquette ]
    vertexAssociated[etiquette] = vertex
    refreshCounters(numberOfVertexes + 1, numberOfLines)
   
def centre(vertex):
    """A csúcsot reprezentáló kör középpontjának kordinátáit adja visszatérési értékül"""
    a, b, c, d = canvas.coords(vertex)
    return (a + c) / 2, (b + d) / 2
    
def createLine(orig, endP):
    """Az orig és endP csúcsokat összekötő él létrehozása"""
    x0, y0 = centre(orig)
    x1, y1 = centre(endP)
    line_ = canvas.create_line(x0, y0, x1, y1)
    
    endPoints[line_] = (orig, endP)
    attributs[orig].append(line_)
    attributs[endP].append(line_)

    refreshCounters(numberOfVertexes, numberOfLines + 1)

def neighbourVertex(x, y):  
    """ Megtalálja az (x, y) ponttal szomszédos csúcsot, vagy None-t.
        A Canvas.find_enclosed -ot használjuk (a Canvas.find_closest helyett)
        azért, hogy elkerüljük egy él kiválasztását"""     
    pres = 10
    objets = canvas.find_enclosed(x - pres, y - pres, x + pres, y + pres)
    if len(objets) > 0:    # ha van...
        return objets[0]   # ...akkor az elsőt vesszük 
    else:
        return None

def replace(line_):
    """Ennek a függvénynek a hívására kerül sor egy végpont mozgatása során"""
    vertex0, vertex1 = endPoints[line_]
    x0, y0 = centre(vertex0)
    x1, y1 = centre(vertex1)
    canvas.coords(line_, x0, y0, x1, y1)
    
def moveVertex(x, y):
    """A vertexToMove csúcs és mindannak az áthelyezése az (x, y) pontba, ami tőle függ
       (az aktuális címkének és az aktuális éleknek)."""
    canvas.coords(vertexToMove, x - R, y - R, x + R, y + R)
    depend = attributs[vertexToMove]
    canvas.coords(depend[0], x + 2 * R, y - R)
    for line_ in depend[1:]:
        replace(line_)

def definitionEtiquette(vertex):
    """A kijelölt csúcshoz definiál egy specifikus címkét"""
    etiquette = attributs[vertex][0]
    texte = canvas.itemcget(etiquette, 'text')
    if not texte.isdigit():
        tkMessageBox.showwarning("Címke definiálása",
                "Ennek a csúcsnak a címkéjét már definiáltuk")
    else:
        texte = tkSimpleDialog.askstring("Etiquette", 
                "Az új érték megadása :", initialvalue = texte) 
        if texte != None:
            canvas.itemconfigure(etiquette, text = texte)
            listeEtiquettes.insert(END, texte)
            vertexAssociated[texte] = vertex

def clearAll():
    """Az összes csúcs és él törlése"""
    canvas.addtag_all("a_effacer")
    canvas.delete("a_effacer")
    listeEtiquettes.delete(0)
    refreshCounters(0, 0)
    
def mettreEnEvidenceSommet(texte):
    """Az adott szövegű címkéhez tartozó csúcs színének és méretének megváltoztatása
       (egy normal <==> piros flip-flop-ról van szó)"""
    vertex = vertexAssociated[texte]
    x, y = centre(vertex)
    if canvas.itemcget(vertex, 'fill') == COLOUR_VERTEX:
        canvas.itemconfigure(vertex, fill=COLOUR_VERTEX2)
        canvas.coords(vertex, x - R2, y - R2, x + R2, y + R2)
    else:
        canvas.itemconfigure(vertex, fill=COLOUR_VERTEX)
        canvas.coords(vertex, x - R, y - R, x + R, y + R)

### Mentés file-ba, visszaállítás file-ból

def saveGraph():
    """A gráf aktuális állapotát egy szövegfile-ba mentjük.
       Nem használhatjuk a pickle modult, mert nem tudjuk milyen struktúúrákat manipulálunk
       (a Canvas fekete doboz aspektusa)"""
    file = tkFileDialog.asksaveasfile()
    if file == None:
        return
    
    liste = canvas.find_all()
    for item in liste:
        if canvas.type(item) == 'oval':
            dep = attributs[item]
            print >> file, '"' + canvas.itemcget(dep[0], 'text') + '"', centre(item),
            for line_ in dep[1:]: 
                neighbour = endPoints[line_][0]
                if neighbour == item:
                    neighbour = endPoints[line_][1]
                print >> file, '"' + canvas.itemcget(attributs[neighbour][0], 'text') + '"',
            print >> file
    
    file.close()

def restoreGraph():
    tkMessageBox.showwarning("Bocsánat...",
            "Ez a funkció még nincs implementálva")

### ESEMÉNYKEZELŐK ##############################################################

application = Tk()
application.title("Edigraph")

### a radiobutton-ok esetében a munka lényegi részét a currentState végzi el
### a következő függvények az állapotsor szövegét kezelik

currentState = StringVar(application)
currentState.set(STATE_CREATION_VERTEX)

def checkBoxCreateVertex():
    statusBar.config(text=HELP_CREATION_VERTEX)

def checkBoxCreateLine():
    statusBar.config(text=HELP_CREATION_LINE)

def checkBoxDefEtiquette():
    statusBar.config(text=HELP__DEFINITION_ETIQUETTE)

### A "Mindent töröl" gombnak csak az után van hatása, hogy a felhasználó jóváhagyta

def pressButtonClear(): 
    if tkMessageBox.askyesno("Figyelem", 
            "Valóban mindent le akar rombolni?"):
        clearAll()    

### választás a listából

def actionOnList(evt):
    selections = listeEtiquettes.curselection()  # ex.: ('3', '5', '9')
    selection = selections[0]                    # ex.: '3'
    i = int(selection)                           # ex.: 3
    texte = listeEtiquettes.get(i)               # le texte correspodant   a megfelelő szöveg
    mettreEnEvidenceSommet(texte)                # la fonction qui bosse   

### a bal egérgombbal kattintás (a kapott hatás az állapottól függ)

def pressButtonLeft(event):
    global vertexSelected

    if currentState.get() == STATE_CREATION_VERTEX:
        createVertex(event.x, event.y)
    
    elif currentState.get() == STATE_CREATION_LINE:
        s = neighbourVertex(event.x, event.y)
        if s != None:
            vertexSelected = s
            currentState.set(ETAT_SUITE_CREATION_ARETE)
            statusBar.config(text=AIDE_SUITE_CREATION_ARETE)
    
    elif currentState.get() == ETAT_SUITE_CREATION_ARETE:
        s = neighbourVertex(event.x, event.y)
        if s != None:
            createLine(vertexSelected, s)
            currentState.set(STATE_CREATION_LINE)
            statusBar.config(text=HELP_CREATION_LINE)
    
    else: # currentState.get() == STATE_DEFINITION_ETIQUETTE
        s = neighbourVertex(event.x, event.y)
        if s != None:
            definitionEtiquette(s)

### akció a jobbegérgombbal (vonszolás - elengedés)

def pressButtonRight(event):
    global vertexToMove
    
    s = neighbourVertex(event.x, event.y)
    if s != None:
        vertexToMove = s

def moveButtonRight(event):
    if vertexToMove != None:
        moveVertex(event.x, event.y)
    
def releaseButtonRight(event):
    global vertexToMove
    
    vertexToMove = None

### menuparancsok

def comMenuQuitter():
    if tkMessageBox.askyesno("Figyelem", 
            "Valóban ki akar lépni a programból ?"):
        sys.exit(0)

def comMenuAPropos():
    tkMessageBox.showinfo(
            "About...",
            "Az Edigraph\n\n" + 
            "egy tisztán demonstratív célú gráfszerkesztő\n" + 
            "a grafikus interface Tkinterrel való megvalósításának bemutatására    \n\n"  + 
            "(C) H. Garreta, 2005")


### FŐPROGRAM ###################################################################

# állapotsor

statusBar = Label(application, text=HELP_CREATION_VERTEX, 
                    bd=1, relief=SUNKEN, anchor=W)
statusBar.pack(side=BOTTOM, fill=X)

# rajzpanel 

canvas = Canvas(application, bg="#C8FFFF", width=400, height=400)
canvas.pack(side=RIGHT, fill=BOTH, expand=True, padx=2, pady=2)

canvas.bind('<Button-1>', pressButtonLeft)
canvas.bind('<Button-3>', pressButtonRight)
canvas.bind('<B3-Motion>', moveButtonRight)
canvas.bind('<ButtonRelease-3>', releaseButtonRight)

### parancspanel (a felső panel)

paneUpper = Frame(application, width=150, height = 200, 
            padx=4, pady=4, bd=2, relief = RIDGE)
paneUpper.pack(side=TOP)

lab = Label(paneUpper, text="Balegérgomb :")
lab.grid(row=0, sticky=W)

rb = Radiobutton(paneUpper, variable=currentState, text='Vertex létrehozása', 
                value=STATE_CREATION_VERTEX, command=checkBoxCreateVertex)
rb.grid(row=1, sticky=W)
rb = Radiobutton(paneUpper, variable=currentState, text='Él létrehozása', 
                value=STATE_CREATION_LINE, command=checkBoxCreateLine)
rb.grid(row=2, sticky=W)
rb = Radiobutton(paneUpper, variable=currentState, text='Címke definiálása', 
                value=STATE_DEFINITION_ETIQUETTE, command=checkBoxDefEtiquette)
rb.grid(row=3, sticky=W)

bouton = Button(paneUpper, text='Mindent töröl', command=pressButtonClear)
bouton.grid(row=4)

### alsó panel

paneLower = Frame(application)
paneLower.pack(side=BOTTOM, fill=Y, expand=True)

lab = Label(paneLower, text="Címkék :")
lab.pack(side=TOP, anchor=W)

etiqNbrOfLines = Label(paneLower)
etiqNbrOfLines.pack(side=BOTTOM, anchor=W)
etiqNbrOfVertexes = Label(paneLower)
etiqNbrOfVertexes.pack(side=BOTTOM, anchor=W)
refreshCounters(0, 0)

listeEtiquettes = Listbox(paneLower)
listeEtiquettes.pack(side=BOTTOM, fill=Y, expand=True)
listeEtiquettes.bind('<Double-Button-1>', actionOnList)

### A menu installálása

menuBar = Menu(application)
application.config(menu = menuBar)

saveGraph = Menu(menuBar)
menuBar.add_cascade(label="File", menu=saveGraph)

saveGraph.add_command(label="Új", command=pressButtonClear)
saveGraph.add_command(label="Megnyitás...", command=restoreGraph)
saveGraph.add_command(label="Mentés, mint...", command=saveGraph)
saveGraph.add_separator()
saveGraph.add_command(label="Kilépés", command=comMenuQuitter)

menuHelp = Menu(menuBar)
menuBar.add_cascade(label="Help", menu=menuHelp)

menuHelp.add_command(label="A propos", command=comMenuAPropos)

### nem marad más hátra, mint az eseményfigyelő működtetése

application.mainloop()