Programmation d`une interface graphique
Transcription
Programmation d`une interface graphique
Algorithmique et Programmation Python Printemps 2013 Bruno Martin & Jean-Paul Roy L1 Sciences Fondamentales - Faculté des Sciences Cours n°11 Programmation classique (séquentielle) http://deptinfo.unice.fr/~bmartin/python.html Initialisation Programmation d'une interface graphique Traitement Terminaison Initialisation : • importe des modules; ouvre des fichiers; accède au réseau Traitement : • gère l'affichage, calcule, modifie les données Terminaison : • quitte proprement l’application Introduction • tkinter : bibliothèque provenant de l’extension graphique Tk du langage Tcl (1988). • L’extension a largement dépassé le cadre de Tcl/Tk. Programmation événementielle Initialisation Traitement (non séquentielle) Terminaison • Tk utilisable dans différents langages (Perl, Python, Ruby, ...) • En python, c’est tkinter : Tk interface • Permet de réaliser un GUI (Graphical User Interface) • GUI : une interface homme-machine permettant à l’utilisateur d’interagir avec la machine autrement que par le shell. Initialisation: • crée les composants graphiques; • fait le lien composant-événement-action Traitement : • créée les fonctions relatives aux actions • se met en attente d’un événement (interaction avec utilisateur) • exécute l’action liée Terminaison : • quitte proprement l’application Gestionnaire d’événements Structure du programme Initialisations événements gestionnaire messages Fonctionnalités du programme Terminaison • écoute les événements des périphériques (clavier, souris, etc) • réagit à l’apparition d’un événement • envoie un message au programme • exécute un bloc de code (fonction ou méthode) spécifique • PROGRAMMATION DIRIGEE PAR LES EVENEMENTS ! from tkinter import * initialisation root=Tk() création de la fenêtre maître message = Label(root,\ text = 'Un premier exemple !'\ fg = 'red') boutonQuit = Button(root,\ text = 'Quit',\ command = root.destroy) message.pack() boutonQuit.pack() affichage des composants root.mainloop() lancer le gestionnaire d’événements exit(0) quitter proprement Les widgets : gadgets de fenêtrage Création de widgets • widget = window gadget : tous les composants de l’écran (fenêtres, boutons, ascenseurs, ...) • Chaque widget est un objet python. • Tk assure la gestion des widgets : - fenêtre de composants (Frame) - fenêtre de dessin (Canvas) - affichage d'informations (Label, Message, Text) - interaction avec les composants (Button, Scale, ...) - saisie de texte (Entry) • Création de widget : passer le parent de la hiérarchie en argument de la fonction de création (sauf pour root). • Les widgets ont beaucoup d’options de configuration (couleur, position, etc...). from tkinter import * root=Tk() etiquette=Label(root,text='Exemple') etiquette.pack() • Tous les widgets sont des éléments d’une hiérarchie : root parent contenu du Frame texte (Label) bouton (Button) définition des composants option de configuration etiquette=Label(root,text='Un premier exemple !',fg='red') boutonQuit=Button(root,text='Quit',command=root.destroy) création bouton interaction avec composant Les couleurs Un petit logiciel d'automate cellulaire 1-D • Une couleur peut s’exprimer : • Il sera constitué de trois acteurs bien distincts : - soit par une chaîne de caractères constante : message['fg']='red' 'red' 'blue' 'black' 'green' 'white' 'yellow' 'gray', etc - soit par un mélange RGB à la place du texte, en hexadécimal message['fg']='#ff0000' Ex : la couleur jaune s’obtient avec un mélange de rouge et de vert: jaune = '#ffff00' ; message['fg'] = jaune - Une partie (le MODELE) sera chargée de décrire le modèle mathématique de calcul, ici par l'intermédiaire d'une classe Python. - Une autre partie (la VUE) sera chargée de visualiser l'état courant du modèle mathématique dans une fenêtre graphique. - Quant à Tkinter (le CONTROLEUR), il jouera le rôle de chef d'orchestre en se mettant à l'écoute de l'utilisateur. Il assurera la synchronisation entre le Modèle et la Vue. http://gnuprog.info/prog/python/pwidget.php NB : Le schéma MVC prend soin de bien séparer les trois parties... Un automate cellulaire 1-D Modèle : une classe CA d’automates cellulaires • Un automate cellulaire à 1 dimension est constitué de cellules disposées sur une ligne. Une cellule peut être morte(0) ou vivante(1). • L'automate va évoluer. A chaque génération, toutes les cellules sont transformées. L'état suivant d'une cellule est fonction de son état actuel et de ceux de ses voisines immédiates. Suivant une REGLE. • Exemple, la règle n° 30 : 111 110 101 100 011 010 001 000 • Pourquoi n° 30 ? A cause du binaire : n n+1 256 règles ! >>> 0b00011110 30 on recolle les bords ! • L'état d'un objet de la classe CA (Cellular Automaton) consiste en la donnée de deux attributs : une configuration et une règle (des listes). >>> ca = CA('0010110',30) >>> bin(30) '0b11110' >>> [0, >>> [0, ca.config 0, 0, 1, 0, 1, 1, 0, 0] ca.regle 0, 0, 1, 1, 1, 1, 0] class CA : def __init__(self,cfg='1011',n=30) : self.config = [int(cfg[-1])] + [int(i) for i in cfg] + [int(cfg[0])] s = [int(i) for i in bin(n)[2:]] self.regle = (8-len(s)) * [0] + s def __str__(self) : return str(self.config[1:-1]) ..... >>> print(ca) [0,0,1,0,1,1,0] L'évolution de l'automate • La méthode next() va faire évoluer la configuration de l'automate, suivant sa règle : >>> print(ca) [0,0,1,0,1,1,0] >>> ca.next() >>> print(ca) [0,1,1,0,1,0,1] # génération suivante ! 111 110 101 100 011 010 001 000 def next(self) : L = len(self.config) * [0] # le résultat à remplir for i in range(1,len(L)-1) : v = self.config[i-1:i+2] # v == [1,1,0] k = int(str(v[0])+str(v[1])+str(v[2]),2) # k == 6 # on récupère donc l'élément numéro 7-k de la règle L[i] = self.regle[7-k] (L[0],L[-1]) = (L[-2],L[1]) # recollement des bords self.config = L Création du canvas 400 x 300 from tkinter import * root=Tk() root.title('automate cellulaire unidimensionnel') canvas=Canvas(root,width=400,height=300,bg='gray') root.mainloop() (0,0) fenêtre principale (root) titre de la fenêtre principale initialisation définition d'un composant affichage du composant canvas.pack(side=left) (0,300) L'interface graphique avec tkinter création de la fenêtre maître (400,0) lancement du gestionnaire d’événements • Mise à part la tortue, il est usuel en programmation de prendre l'origine des coordonnées en haut à gauche, l'axe 0y vers le bas ! Dessiner et écrire dans le canvas from tkinter import * root = Tk() Bouton pour quitter Bouton pour exécuter zone d'affichage (canvas) champ de saisie du numéro de la règle Texte fixe champ de saisie de la configuration initiale Texte fixe root.title('Automate cellulaire unidimensionnel') canvas=Canvas(root,width=400,height=300,bg='gray') canvas.pack(side=left) canvas.create_oval( 40,20,120,200 ,outline="red",fill="green", width=2) canvas.create_rectangle(230,50,320,100,fill='yellow',width=10) canvas.create_line(40,20,120,200) canvas.create_text(200,150,\ text="Je sais écrire !!!",\ font=('copperplate',36)) root.mainloop() Saisir une entrée et récupérer le contenu • Le composant dans lequel l'utilisateur peut entrer la configuration est dans la classe Entry de tkinter. Idem pour le composant dans lequel il entrera le numéro de règle. Plaçons ces deux composants dans le canvas. config = Entry(canvas) config.pack() canvas.create_window(175,280,\ width=250,window=config) canvas.create_text(25,280,text='config') rule = Entry(canvas) rule.pack() canvas.create_window(370,280,\ width=35,window=rule) canvas.create_text(330,280,text='rule') 250 (175,280) • On pourra récupérer le contenu de l'Entry rule par : rule.get() qui retournera une chaîne de caractères ! Les deux boutons et leur callback • Un bouton est un composant de la classe Button de tkinter. Son attribut le plus important est command, contenant une fonction d'arité 0. Cette fonction (le callback du bouton) sera automatiquement exécutée suite à un clic de l'utilisateur dans le bouton. boutonQuit = Button(root,text='Quit',command=root.quit) boutonRun = Button(root,text='Run',command=executer) boutonQuit.pack() boutonRun.pack() • La fonction root.quit() est définie par tkinter, elle termine le logiciel ! • Il vous reste à définir en TP la fonction executer() qui va construire un automate cellulaire et en dessiner 30 générations dans le canvas... Résumé de l'interface graphique root=Tk() root.title('Automate cellulaire unidimensionnel') fenêtre principale (root) titre fenêtre principale Bouton quitter affichage (canvas) canvas=Canvas(width=400,height=300,bg='gray') canvas.pack(side=LEFT) Bouton Run champ saisie rule Texte config rule=Entry(canvas,width=20) rule.pack() canvas.create_window(370,280,\ width=35,window=rule) canvas.create_text(25,280,text="config") Texte rule champ saisie config canvas.create_text(330,280,text="rule") config=Entry(canvas) config.pack() canvas.create_window(175,280,width=250,window=config)