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.

Personaliser un widget

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 un jeu de carte très élémentaire Capture

Lorsque une carte est cliquée, nous souhaitons qu'elle se retourne. Nous allons donc déninir notre propre widget personalisé qui représentera une carte et qui gèrera le clic de souris.

Création du nouveau widget

In [ ]:
class Carte(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        
        self.pixmap=QPixmap('carte2.gif')
        self.resize(self.pixmap.size())
        self.repaint()
    
    def paintEvent(self,e):
        painter=QPainter(self)
        painter.drawPixmap(0,0,self.pixmap)

Quelques explications

Nous créons donc un widget Carte qui hérite de la classe QWidget, ce qui est assez naturel.

Ensuite, nous définissons l'image qui sera dessinée sur ce widget. Cette image est du type QPixmap (RTFM).La méthode _init() va aussi définir la taille du widget en fonction de la taille de l'image.

Vient ensuite l'appel à la méthode repaint() de QWidget. Cet appel force le widget à se redessiner.

Mais comment dessine t-on un widget ? chaque widget possède une méthode nommée paintEvent() qui est appelée chaque fois que le widget veut s'afficher ou que repaint() ou update() est appelée. En redéfinissant cette méthode, on peut redessiner notre widget de la manière qu'on souhaite.

Dans l'exemple ci-dessus, la méthode paintEvent() se contente d'afficher le pixmap que l'on a chargé dans la méthode init() tout simplement.

Créons à présent un dialogue pour afficher nos cartes

Ce dialogue très élémentaire affiche un fond vert et réagit au clic de souris sur le tapis de jeu. A chaque clic, une carte est crée et affichée à l'emplacement du clic.

In [ ]:
WIDTH,HEIGHT=800,600
class MainWindow(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        
        self.setAutoFillBackground(True)
        p = self.palette()
        p.setColor(self.backgroundRole(), Qt.green)
        self.setPalette(p)
             
        self.setFixedSize(WIDTH,HEIGHT)
        
        self.setWindowTitle("Jeu de cartes")
        
    def mousePressEvent(self,e) :
        carte=Carte(self)
        carte.move(e.x(),e.y())
        carte.show()

Testons ce dispositif !

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

A vous de jouer

Nous souhaiterions qu'en cas de clic sur une carte, elle se retourne. Pour le moment ce n''est pas le cas : en effet, notre widget n'est pas programmé pour réagir au clic de souris. Si on clique sur une carte, c'est le tapis qui intercepte l'événement en créant une nouvelle carte.

Ce qu'il vous faudra faire c'est rendre votre widget carte sensible au clic de souris en implémentant dans la classe Carte la méthode mousePressEvent().

Cette méthode devra redéfinir le pixmap avec la bonne image : carte1.gif ou carte2.gif selon qu'on affiche le dos ou le devant de la carte. L'exemple donné dans l'initialisation de la carte devrait vous suffire. N'oubliez pas à la fin de la méthode mousePressEvent() de forcer le réaffichage de la carte par un repaint() !

In [ ]:
# Redéfinissez votre classe Carte ici

testez votre nouvelle classe. Le tapis de jeu (objet form) n'ayant pas changé, il suffit de relancer l'app.

In [ ]:
form = MainWindow()
form.show()
app.exec_()
In [ ]: