Cette page présente le même programme, qui affiche une fenêtre contenant deux rectangles, une image et un segment, en utilisant tkinter
ou ''PySide''.
Voici ce qu'affichent les programmes :
Cet avis n'engage que moi : PySide (Qt) est plus moderne que Tk, il contient des Widgets plus complexes et plus complets. Cependant, il est moins standard en Python que tkinter, et il est plus complexe (pour faire des choses simples, c'est a priori aussi simple, mais si on entre dans les détails…). On peut toutefois réaliser avec PySide des choses qui seraient compliquées à faire avec Tkinter… Il y a aussi d'autres outils pour réaliser des interfaces graphiques, dont Kivy, qui vaut probablement la peine qu'on s'y attarde.
Pour tester les programmes suivants, il faut aussi avoir l'image utilisée. Merci de la télécharger :
# Documentation : http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html import tkinter from PIL import ImageTk # Variable globale pour le logo (voir plus loin) image = None # Si on clique dans la fenêtre, on verra les coordonnées s'afficher dans le terminal def click(event): print("clic souris : ", event.x, event.y) # L'application sera contenue dans une /Frame/ (un conteneur). # Cette frame contiendra un /Canvas/ qui contiendra des objets graphique. # On peut faire ce programme *sans* utiliser de /Frame/, mais directement le # canvas. Cependant, si par la suite on souhaite ajouter d'autres éléments graphiques # ce sera tout prêt... def gui(parent): # Titre de l'application : parent.title("Example graphique Tkinter sans classe") # Création de la Frame frame = tkinter.Frame(parent) # Disposition de la Frame (dans la fenêtre application). La frame va prendre toute la place # disponible dans la fenêtre, même si on change la taille de la fenêtre frame.pack(fill='both', expand=1) # On crée un canevas de taille 400x300 dans la Frame canvas = tkinter.Canvas(frame, width=300, height=400, background="grey") # Le canevas est "packé" dans sa fenêtre en laissant une petite bordure de taille 8 canvas.pack(padx=8, pady=8)# Ajouter fill='both', expand=1 pour voir... draw_board(canvas) # On demande à associer la callback /click/ à l'événement /<Button-1>/ canvas.bind("<Button-1>", click) def draw_board(canvas): global image # On trace un rectangle rouge : coin hg 10,10, coin bd 100,20 canvas.create_rectangle(10, 10, 100, 30, fill="#ff0000") # Puis un bleu canvas.create_rectangle(80, 20, 200, 60, fill="#0000ff", outline="#00ff00") # On trace une ligne violette canvas.create_line(0, 0, 200, 300, fill="#ff00ff") # On charge l'image image = ImageTk.PhotoImage(file="python.png") # Et on l'affichge, les coordonnées sont celles du centre (anchor="c") canvas.create_image(128,128, image=image, anchor="c") # Attention, on ne peut pas utiliser de variable locale pour l'image car après avoir # donné l'ordre d'affichage /create_image/ Tk doit pouvoir continuer à disposer des données. # Or les variables locales sont libérées (et l'image effacée) à la sortie de la fonction # qui les contient. C'est pourquoi on utilise ici une variable globale (il y a d'aurtes solutions # toutefois... # Création de l'application root = tkinter.Tk() # Ajout des éléments graphiques gui(root) # Boucle des événements root.mainloop()
# Documentation : http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html import tkinter from PIL import ImageTk # Si on clique dans la fenêtre, on verra les coordonnées s'afficher dans le terminal def click(event): print("clic souris : ", event.x, event.y) # L'application sera contenue dans un objet qui hérite de /Frame/ (un conteneur). # Cette frame contiendra un /Canvas/ qui contiendra des objets graphique. # On peut faire ce programme *sans* utiliser de /Frame/, mais directement le # canvas. Cependant, si par la suite on souhaite ajouter d'autres éléments graphiques # ce sera tout prêt... class Fenetre(tkinter.Frame): def __init__(self, parent): # Initialiseur de la classe parente : super().__init__(parent) # Titre de l'application : parent.title("Example graphique Tkinter avec classe") # Disposition de la Frame (dans la fenêtre application). La frame va prendre toute la place # disponible dans la fenêtre, même si on change la taille de la fenêtre self.pack(fill='both', expand=1) # On crée un canevas de taille 400x300 dans la Frame /self/ self.canvas = tkinter.Canvas(self, width=300, height=400, background="grey") # Le canevas est "packé" dans sa fenêtre en laissant une petite bordure de taille 8 self.canvas.pack(padx=8, pady=8)# Ajouter fill='both', expand=1 pour voir... self.image = None # initialisation propre d'un attribut utilisé plus loin # On dessine self.draw_board() # On demande à associer la callback /click/ à l'événement /<Button-1>/ self.canvas.bind("<Button-1>", click) def draw_board(self): # On trace un rectangle rouge : coin hg 10,10, coin bd 100,20 self.canvas.create_rectangle(10, 10, 100, 30, fill="#ff0000") # Puis un bleu self.canvas.create_rectangle(80, 20, 200, 60, fill="#0000ff", outline="#00ff00") # On trace une ligne violette self.canvas.create_line(0, 0, 200, 300, fill="#ff00ff") # On charge l'image self.image = ImageTk.PhotoImage(file="python.png") # Et on l'affichge, les coordonnées sont celles du centre (anchor="c") self.canvas.create_image(128,128, image=self.image, anchor="c") # Attention, on ne peut pas utiliser de variable locale pour l'image car après avoir # donné l'ordre d'affichage /create_image/ Tk doit pouvoir continuer à disposer des données. # Or les variables locales sont libérées (et l'image effacée) à la sortie de la fonction # qui les contient. C'est pourquoi on utilise ici un attribut de classe. self.image a ainsi # la même durée de vie que l'objet global /gui/ (voir plus bas) def main(): # Création de l'application root = tkinter.Tk() # Ajout des éléments graphiques gui = Fenetre(root) # Boucle des événements root.mainloop() if __name__ == "__main__": main()
# Documentations : # https://deptinfo-ensip.univ-poitiers.fr/ENS/doku/doku.php/stu:python_gui:pyqt # https://deptinfo-ensip.univ-poitiers.fr/ENS/pyside-docs/index.html from PySide import QtGui,QtCore import sys # Fenêtre principale (c'est une Frame), qui contient : une Frame et une # zone de dessin (dans la frame intérieure) class Fenetre(QtGui.QFrame): def __init__(self,parent=None) : super().__init__(parent) # Titre de l'application : self.setWindowTitle("Example graphique PySide (avec classes...)") # On place une première /Frame/ (conteneur), un peu plus petit. frame = QtGui.QFrame(self) frame.setGeometry(10,10,300,400) frame.setStyleSheet("background:grey") # Puis une zone de dessin (définie dans la classe /ZoneDessin/ plus loin, # qui occupe toute la frame (la plus petite) dessin=ZoneDessin(frame) dessin.setGeometry(0,0,300,400) # Zone principale (dessin) class ZoneDessin(QtGui.QWidget) : def __init__(self,parent=None) : super().__init__(parent) def paintEvent(self,e) : # On demande un pbjet Painter et on dessine dessus p=QtGui.QPainter(self) # On trace un rectangle rouge à bord noir (x,y du coin puis largeur hauteur) p.setPen(QtGui.QColor(0,0,0)) p.setBrush(QtGui.QColor(255,0,0)) p.drawRect(10, 10, 90, 20) # puis un bleu à bord vert p.setPen(QtGui.QColor(0,255,0)) p.setBrush(QtGui.QColor(0,0,255)) p.drawRect(80,20,120,40) # On trace une ligne violette p.setPen(QtGui.QColor(255,0,255)) p.drawLine(0, 0, 200, 300) # On affiche l'image pixmap = QtGui.QPixmap("python.png") p.drawPixmap(78, 78, pixmap) # Si on clique dans la fenêtre, on verra les coordonnées s'afficher dans le terminal def mousePressEvent(self, e): print("clic souris : ",e.x(), e.y()) app=QtGui.QApplication(sys.argv) frame=Fenetre() frame.show() sys.exit(app.exec_())