Afin de pouvoir personnaliser votre classeur sans détruire le classeur sur lequel travaille votre voisin, vous allez tout d'abord aller dans le menu File puis Make a copy.... Renommez le classeur en ajoutant votre nom à la fin du nom de fichier par exemple.

Dessiner des formes dans une fenêtre

Lien vers la doc

On commence bien sûr par rappeler le lien vers la doc PySide...

https://deptinfo-ensip.univ-poitiers.fr/ENS/pyside-docs/index.html

On importe les librairies Qt comme d'habitude

In [ ]:
from PySide.QtCore import *
from PySide.QtGui import *
import sys

Le but de l'activité

Nous souhaitons réaliser une application dessinant un rectangle rouge au clic de souris

Capture

Le rectangle est placé à l'emplacement du clic. Des boutons effacer et Quitter sont présents également.

Nous verrons

  • La détection du clic de souris sur un widget (événement standard)
  • deux nouveaux objets liés l'un à l'autre pour dessiner : la vue et la scène

Introduction aux scènes et aux vues

Lorsque nos avons besoin de dessiner de nombreux objets sur une surface 2D (lignes, rectangles, cercles, polygones ...), et éventuellement d'interagir avec (sélectionner, déplacer...) nous avons recours aux scènes et aux vues Qt.

Nous allons voir ici de nouvelles classes Qt très pratiques : QGraphicsView (la vue), QGraphicsScene (la scène) et QGraphicsItem (et surtout ses dérivés : les objets que l'on affiche)

Le coin des docs

  • QGraphicsView
  • QGraphicsScene
  • QGraphicsItem et ses enfants
    • QGraphicsEllipseItem
    • QGraphicsLineItem
    • QGraphicsPathItem (chemin arbitraire)
    • QGraphicsPixmapItem (image)
    • QGraphicsPolygonItem
    • QGraphicsRectItem (celui que nous utiliserons)
    • QGraphicsSimpleTextItem
    • QGraphicsTextItem

Passons à l'exemple et aux explications.

Le programme

In [ ]:
WIDTH,HEIGHT=800,600

class MainWindow(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        
        # On définit la vue et la scène
        self.scene=QGraphicsScene()
        self.view = QGraphicsView(self.scene) # On relie la vue à la scène
        self.view.setSceneRect(0,0,WIDTH,HEIGHT)
               
        self.clearBtn=QPushButton("Effacer")
        self.quitBtn=QPushButton("Quitter")
                
        layout=QVBoxLayout()
        layout.addWidget(self.view)
        layout1=QHBoxLayout()
        layout1.addWidget(self.clearBtn)
        layout1.addWidget(self.quitBtn)
        layout.addLayout(layout1)      
        self.setLayout(layout)          
        
        self.quitBtn.clicked.connect(self.Quitter)
        self.clearBtn.clicked.connect(self.clear)
        
        self.setWindowTitle("Dessiner dans une fenêtre")
    
    def mousePressEvent(self,e) :
        # Conversion des coord fenêtre en coord View :
        c=e.pos()-self.view.pos()
        # Ajout d'un QGraphicsItem rectangle
        self.scene.addRect(QRect(c.x(),c.y(),60,40),QPen(Qt.red))
        
    def clear(self):
        self.scene.clear()
        
    def Quitter(self):
        self.close()
        app.quit()

Jouons un peu avec le programme à présent, avant de passer aux explications

In [ ]:
try:
    app = QApplication(sys.argv)
except RuntimeError:
    app=QApplication.instance()
form = MainWindow()
form.show()
app.exec_()

Passons sur la définition des objets de l'interface (boutons, layouts) : que du classique.

La première chose importante à noter est la définition de la vue et de la scène ensemble par ces 2 lignes

self.scene=QGraphicsScene()
self.view = QGraphicsView(self.scene)

En passant self.scene à la classe QGraphicsView, on indique à la vue quelle scène elle doit afficher. On peut le faire à postériori via la méthode setScene().

On règle enfin la taille de notre surface

self.view.setSceneRect(0,0,WIDTH,HEIGHT)

C'est tout. On est prêt à dessiner

Capture des clics de souris

L'objet QWidget nous fournit en standard un certain nombre d'événements. Pour les capturer, il suffit de surcharger les méthodes correspondantes. Cela se fait pour le clic de souris par la définition de la méthode :

def mousePressEvent(self,e):

e désigne l'objet événement qui va nous permettre de récupérer les coordonnées du clic de souris par les méthodes e.x() et e.y() tout simplement.

dessin d'un rectangle

Le dessin du rectangle se fait par l'appel

self.scene.addRect(QRect(c.x(),c.y(),60,40),QPen(Qt.red))

La doc expliquera si besoin les paramètres.

A vous de jouer

Pour vous entraîner, essayez de modifier le programme afin d'afficher des ronds pleins bleus

In [ ]:
# Votre classe ici
In [ ]:
try:
    app = QApplication(sys.argv)
except RuntimeError:
    app=QApplication.instance()
form = MainWindow()
form.show()
app.exec_()
In [ ]: