Quando lavorate in linea di comando, potete sostituire le Entry con le funzioni di input, e le Label con le istruzioni print. Quello che non potete sostituire è il disegno di grafici, disegni o schemi, per cui il widget Canvas risulta insostituibile.
Nella sua forma più semplice una canvas non è che un riquadro di dimensioni scelte in fase di configurazione, che permette di tracciare punti, linee, ovali, rettangoli e anche di renderizzare un testo. Unitamente alla libreria PIL (Python Image Library), consente di importare immagini di vario formato, che possono essere collocate staticamente nella canvas o fatte muovere con tastiera e mouse o cun un algoritmo.
Piuttosto di installare PIL, su Ubuntu, ho preferito un suo fork, pillow, che promette di essere maggiormente user friendly; perchè funzioni correttamente è pero' necessario preliminarmente (re)installare le librerie tk e tcl:
sudo apt-get install tk8.5-dev tcl8.5-dev sudo pip install pillow
Per esemplificare l'uso della Canvas creiamo una piccola applicazione test con due Frame, la prima contiene una Canvas, la seconda due Button e due Label.
Nella Canvas simuliamo un circuito automobilistico con una Porsche Carrera, ripresa dall'alto, che gira in un'orbita fissa ma di cui possiamo variare la velocità. Non è il gioco più divertente dell'anno ma credo che abbia una discreta efficacia didattica. Rimando le spiegazioni al prossimo post.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | # -*- coding: utf-8 -*- import Tkinter from PIL import Image, ImageTk import math class Carrera: """ Classe utile per creare un'oggetto immagine della Porsche Carrera e ruotarla in relazione alla posizione angolare sulla traiettoria ellittica """ def __init__(self, canvas, image, x, y, angolo): self.image = image self.image = self.image.rotate(angolo) self.car = ImageTk.PhotoImage(self.image) canvas.create_image(x, y, image=self.car, tag='myCarrera') def update(self, canvas, image, angolo): self.image = image self.image = self.image.rotate(angolo) self.car = ImageTk.PhotoImage(self.image) canvas.itemconfig('myCarrera', image=self.car) class MyApp: def __init__(self): self.root = Tkinter.Tk() self.root.title('Indianapolis') self.coefficiente=1.0 #Frame 1 self.frame1 = Tkinter.Frame() self.frame1.pack(side='left') self.width = 600.0 self.height= 600.0 #Canvas self.canvas = Tkinter.Canvas(self.frame1, background = 'green', width=self.width, height=self.height) self.canvas.pack() self.eccentricita = .8 self.angolo = 0 # disegna il bordo esterno della pista coord=self.coord_ell(self.eccentricita, self.width, self.height, self.angolo, 100) self.circ1 = self.canvas.create_oval(coord[0],coord[1],coord[2],coord[3], dash = 10, fill='white', width=2) # disegna il bordo interno della pista coord=self.coord_ell(self.eccentricita, self.width, self.height, self.angolo, 60) self.circ2 = self.canvas.create_oval(coord[0],coord[1],coord[2],coord[3], dash = 10, fill='grey', width=1) # Car # usare l'istruzione seguente dopo aver salvato l'immagine della # Porsche Carrera che compare nella pagina del blog # nella stessa directory del file .py photo=Image.open('CarreraTop1.png') self.carrera_photo=photo.resize((50,50),Image.ANTIALIAS) # traiettoria dell'auto coord=self.coord_ell(self.eccentricita, self.width, self.height, self.angolo, 90) self.carrera = Carrera(self.canvas, self.carrera_photo, coord[4], coord[5], self.angolo) # inizializza il timer self.root.after(50, self.muovi) #Frame2 self.frame2 = Tkinter.Frame() self.frame2.pack(side='left') self.label1 = Tkinter.Label(self.frame2, text = 'Indianapolis\nclicca + per accelerare\n- per decelerare', font = 'Helvetica 14', width=20) self.label1.pack() # acceleratore self.button_acc=Tkinter.Button(self.frame2, text = '+', font = 'Courier 34', command=self.accelera) self.button_acc.pack(fill= 'x') # deceleratore self.button_dec=Tkinter.Button(self.frame2, text = '-', font = 'Courier 34', command=self.decelera) self.button_dec.pack(fill= 'x') # indica la velocità self.label2 = Tkinter.Label(self.frame2, text = 'velocità: 1.0', width=20) self.label2.pack() def coord_ell(self, e, width, height, angolo, perc): """ Funzione che, data l'eccentricità di un'ellisse, le dimensioni x e y della canvas, l'angolo al centro e la percentuale dimensionale, restituisce una tupla, con le coordinate x1 y1 x2 y2 (bbox) per ovali ed eventualmente rettangoli, le coordinate x e y dell'ellisse dato l'angolo al centro """ a=width/2*perc/100 c=a*e b=math.sqrt(a*a-c*c) x1=width/2-a y1=(height/2-b) x2=width/2+a y2=(height/2+b) return (x1,y1,x2,y2,a*math.cos(angolo)+self.width/2,b*math.sin(angolo)+self.height/2) def muovi(self): """ Posizionamento assoluto di un oggetto self.carrera in un orbita ellittica al 90% dell'ampiezza """ self.angolo -= self.coefficiente*math.pi/180 self.eccentricita = 0.9 coord= self.coord_ell(self.eccentricita, self.width, self.height, self.angolo, 90) self.carrera.update(self.canvas, self.carrera_photo, -self.angolo*180/math.pi) self.canvas.coords('myCarrera',coord[4],coord[5]) self.timer = self.root.after(50, self.muovi) def accelera(self): self.coefficiente*=1.1 self.label2.config(text = 'velocità : + %2.2f' % (self.coefficiente)) def decelera(self): self.coefficiente*=0.9 self.label2.config(text = 'velocità : + %2.2f' % (self.coefficiente)) def mainloop(self): self.root.mainloop() app = MyApp() app.mainloop() |
No comments:
Post a Comment