Plan du site  
français  English
pixel
pixel

Articles - Étudiants SUPINFO

Chapitre 08 - Interfaces graphiques

Installation et premiers pas

Nous allons dans cette partie présenter la librairie graphique Pygame et étudier un premier code contenant les fondamentaux des GUI.

GUI et CLI

Les programmes que nous avons écrits jusqu’à maintenant possédaient une CLI, Command Line Interface. Cela signifiait que l'utilisateur d'un programme dialoguait avec celui-ci par l'unique intermédiaire de la console. Les possibilités d’affichages et d’interactions étaient donc bien évidemment limitées.

Nous allons maintenant concevoir des programmes avec une GUI, Graphic User Interface. Cela va nous permettre de développer des applications bien plus conviviales.

De nombreux choix de librairies graphiques compatibles avec Python 3 s'offrent aux développeurs :

  • Tkinter

  • PySFML

  • PyQt

  • PyGTK

  • Pygame

  • etc.

L'auteur de ce cours a opté pour Pygame, et ce pour plusieurs raisons :

  • Cette librairie est populaire, de nombreux petits jeux ont par exemple été développés avec.

  • Elle est compatible avec les trois principaux systèmes d'exploitation que sont Windows, macOS et Linux.

  • Elle est facile à installer et à utiliser.

  • Elle est très bien documentée.

[Note]

Le lecteur curieux pourra par exemple consulter le livre en ligne Making Games with Python & Pygame.

Certains exemples de la suite de ce cours sont d'ailleurs inspirés de ceux de cet ouvrage.

Télécharger Pygame

La page de téléchargement du site officiel de Pygame n'est pas à jour. On utilisera donc de préférence cette ressource.

[Note]

Si certains utilisateurs de macOS rencontrent des difficultés lors de l'installation de Pygame, qu'ils consultent ce lien ou celui-ci.

Pour vérifier que l'installation s'est bien passée, il suffit de la tester en tapant import pygame dans la console. Ne pas recevoir de message d'erreur sera alors bon signe.

Un premier code

On va dans cette sous-partie présenter un exemple de code contenant certaines des étapes fondamentales que l'on retrouvera dans la plupart des programmes possédant une GUI. Les commandes rencontrées seront ensuite décrites plus précisément dans les parties suivantes de ce chapitre.

import pygame
from pygame.locals import *
pygame.init()
maSurface = pygame.display.set_mode((500,300))
pygame.display.set_caption('Hello SUPINFO')
inProgress = True
while inProgress:
    for event in pygame.event.get():
        if event.type == QUIT:
            inProgress = False
    pygame.display.update()
pygame.quit()

Si l'on exécute ce code on obtient ceci :

Nous avons ainsi créé une fenêtre de 500 pixels de largeur et 300 pixels de hauteur qui porte le titre "Hello SUPINFO". Même si ce résultat est évidemment bien modeste, nous pouvons tout de même identifier sept points importants dans le programme précédent que l'on retrouvera dans beaucoup d'autres.

Nous allons maintenant prendre le temps de les étudier en détail.

Les imports

import pygame
from pygame.locals import *

Ces deux imports mettent à notre disposition les fonctions et constantes de Pygame qui seront nécessaires pour développer nos applications.

L'initialisation

pygame.init()

Cette commande permet l’initialisation de toutes les fonctions et constantes dont nous aurons besoin. Il n’est pas nécessaire de connaître son fonctionnement exact, il suffit juste de retenir qu’elle est indispensable.

La création de la surface

maSurface = pygame.display.set_mode((500,300))

On créé ici une surface de 500 pixels de largeur et 300 pixels de hauteur, puis l'on affecte cette surface à une variable nommée maSurface. Cette via cette variable que l'on effectuera toutes les modifications voulues sur notre surface.

Donner un titre à la fenêtre

pygame.display.set_caption('Hello SUPINFO')

Ici on donne comme titre à la fenêtre la chaîne de caractère passée en paramètre.

La boucle de jeu

inProgress = True
while inProgress:
    for event in pygame.event.get():
        ...

La boucle principale (i.e. la plus externe) est contrôlée par un while, cela signifie que tant que la variable booléenne inProgress ne sera pas mise à jour elle s'exécutera. Cette sortie de boucle via la modification de inProgress sera commandée par l’exécution d’un événement de l’utilisateur, comme l'appui sur une certaine touche ou un clic de souris.

La seconde boucle permet justement de traiter les événements du clavier ou de la souris selon leur ordre d’apparition.

La sortie de la boucle de jeu

if event.type == QUIT:
    inProgress = False

On teste si le type de l’événement est QUIT, ce qui correspond à un clic sur la croix de la fenêtre et donc une demande de fermeture de celle-ci. Si cet événement se produit, on met à jour la variable booléenne inProgress afin de terminer la boucle principale.

La mise à jour à l'écran de la surface

pygame.display.update()

Cette commande permet d’afficher à l’écran les éventuels changements apportés à la surface. Il faudra bien penser au fait qu’une modification de la surface (tracé, déplacement d’une image, ...) ne sera pas visible tant que cette commande n’est pas exécutée.

[Note]

La principale différence entre ce code et d'autre plus élaborés résidera principalement dans la complexité de la boucle de jeu.

Programmes pilotés par les événements

En mode CLI, on dit que le programme pilote les événements. Même si de l’interactivité est possible, elle est uniquement à l’initiative du programme. C’est ce dernier qui impose en particulier l’ordre des saisies de l’utilisateur.

Par exemple, dans un jeu de morpion c’est le programme qui va demander au joueur sur quelle case il veut poser un pion. Puis plus tard s’il veut refaire une autre partie. Mais ces étapes ne pourront pas s’inverser, car c'est le programme qui décide de l’ordre.

Figure 1.1. Représentation de l'exécution d'un programme CLI

Représentation de l'exécution d'un programme CLI

[Note]

Ce schéma et le suivant se trouvent dans le livre de Gérard Swinnen, "apprendre à programmer avec Python", éditions Eyrolles.

En mode GUI, on dit que le programme est piloté par les événements. La phase de réception des événements est permanente et traite ceux-ci selon leurs ordres d’apparition. Selon la nature de ces événements, telle ou telle fonctionnalité du programme est exécutée. Cette fois-ci l’ordre des exécutions des fonctionnalités est laissée à l’utilisateur.

Dans le jeu du morpion, un joueur mauvais perdant pourra par exemple choisir de faire une nouvelle partie au lieu de jouer son coup.

Figure 1.2. Représentation de l'exécution d'un programme GUI

Représentation de l'exécution d'un programme GUI

La phase de réception des événements est implémentée avec une boucle qui tourne tant qu’aucun événement ne se produit. Il va sans dire que la réception d’événements conduira à une mise à jour de la fenêtre graphique.

Figure 1.3. Autre représentation de l'exécution d'un programme GUI

Autre représentation de l'exécution d'un programme GUI

Premiers dessins

Nous allons dans cette partie apprendre à dessiner des formes géométriques et à afficher des images.

Le système de coordonnées

La surface sur laquelle on va dessiner et insérer des images peut être vue comme un tableau de pixels.

Commençons par présenter la commande qui va nous permettre de définir une surface de l pixels de largeur et de h pixels de hauteur :

maSurface = pygame.display.set_mode((l,h))
[Note]

Il est important de noter que le paramètre de cette fonction de création de surface est un t-uple.

Chaque pixel de la surface est reperé par un t-uple x y , où x est un entier compris entre 0 et l - 1 , et y un entier compris entre 0 et h - 1 .

Example 1.1. Une surface de 16 pixels de largeur et 9 pixels de hauteur

Tous les pixels de la surface sont blancs sauf ceux de coordonnées 7 0 et 2 7 :


[Note]

Comme dans un repère cartésien classique on repère donc d'abord l'abscisse puis l'ordonnée. Il faut juste faire attention au fait que l'axe des ordonnées est orienté vers le bas.

Les couleurs

Les différentes couleurs que l'on va utiliser seront codées en RVB (Rouge Vert Bleu). Cela signifie que chaque couleur est représentée par un t-uple r v b , où r, v et b sont des entiers compris entre 0 et 255.

[Note]

Voir par exemple wikipedia pour plus de détails sur ce système de codage.

Pour améliorer la lisibilité de nos codes, on prendra l’habitude de déclarer des constantes correspondantes aux différentes couleurs que l’on utilisera :

  • BLUE = 0 0 255

  • BLACK = 0 0 0

  • WHITE = 255 255 255

  • etc.

Par défaut, à la création d’une surface celle-ci est noire. Pour modifier sa couleur de fond, on utilisera la commande :

maSurface.fill(COLOR)

Dessiner des formes géométriques usuelles

Nous allons présenter ici les commandes permettant de dessiner des segments, polygones, rectangles, cercles et ellipses.

Dans toute la suite de cette sous-partie, on supposera que l'on dispose d'une surface nommée maSurface et d'une couleur appelée COLOR. Nos dessins se feront sur cette surface et avec cette couleur.

Dessin d'un segment

Voici la commande pour tracer un segment du point de coordonnées x y vers le point z t :

pygame.draw.line(maSurface,COLOR,(x,y),(z,t),epaisseur)

Le paramètre épaisseur correspond à l'épaisseur en pixels du segment. Il vaut 1 par défaut.

Dessin d'un polygone

Voici la commande pour tracer un polygone fermé du point de coordonnées x y vers le point u v en passant par les points z t , etc. :

pygame.draw.polygon(maSurface,COLOR,((x,y),(z,t),...,(u,v)),epaisseur)

Le paramètre épaisseur correspond à l'épaisseur en pixels du polygone. Il vaut 0 par défaut, ce qui correspond à un polygone plein.

[Note]

Le fait que le polygone soit fermé signifie qu'il y aura un segment entre le dernier point et le premier.

Dessin d'un rectangle

Voici la commande pour tracer un rectangle de largeur l pixels, de hauteur h pixels, et dont le sommet en haut à gauche a pour coordonnées x y :

pygame.draw.rect(maSurface,COLOR,(x,y,l,h),epaisseur)

Le paramètre épaisseur correspond à l'épaisseur en pixels du rectangle. Il vaut 0 par défaut, ce qui correspond à un rectangle plein.

[Note]

Les côtés d'un tel rectangle seront nécessairement parallèles aux axes. Si l'on souhaite incliner notre rectangle il faudra utiliser la commande de dessin d'un polygone.

Dessin d'un cercle

Voici la commande pour tracer un cercle dont le centre a pour coordonnées x y , et dont le rayon vaut r :

pygame.draw.circle(maSurface,COLOR,(x,y),r,epaisseur)

Le paramètre épaisseur correspond à l'épaisseur en pixels du cercle. Il vaut 0 par défaut, ce qui correspond à un disque.

Dessin d'une ellipse

Voici la commande pour tracer une ellipse dont le rectangle tangent a pour paramètres x y l h :

pygame.draw.ellipse(maSurface,COLOR,(x,y,l,h),epaisseur)

Le paramètre épaisseur correspond à l'épaisseur en pixels de l'ellipse. Il vaut 0 par défaut, ce qui correspond à une ellipse pleine.

Exemple récapitulatif

Le code suivant contient un exemple de chacune de ces commandes :

import pygame
from pygame.locals import *
WHITE = (255,255,255)
BLUE = (0,0,255)
GREEN = (0,255,0)
RED = (255,0,0)
BLACK = (0,0,0)
pygame.init()
maSurface = pygame.display.set_mode((500, 300))
pygame.display.set_caption('Hello SUPINFO')
maSurface.fill(RED)
pygame.draw.rect(maSurface,BLUE,(10,10,200,100))
pygame.draw.line(maSurface,BLUE,(20,200),(200,250),5)
pygame.draw.circle(maSurface,WHITE,(400,100),20)
pygame.draw.polygon(maSurface,BLACK,((400,70),(440,80),(440,130),(290,130),(270,100)),1)
pygame.draw.ellipse(maSurface,GREEN,(250,200,100,50))
inProgress = True
while inProgress:
    for event in pygame.event.get():
        if event.type == QUIT:
            inProgress = False
    pygame.display.update()
pygame.quit()

Voici le résultat de l'exécution de ce code :

[Note]

Que le lecteur prenne bien le temps de disséquer le code précédent, et voir ainsi le fonctionnement de chacune des commandes.

Ne pas oublier en particulier le rôle fondamental de pygame.display.update(), qui permet de rendre visibles à l'écran les modifications effectuées sur la surface.

Une autre représentation des rectangles

Nous allons voir ici comment créer un rectangle indépendamment de toute surface. On utilise pour ce faire la commande Rect :

monRectangle = pygame.Rect(x,y,l,h)

Les quatre paramètres ont le même sens que ceux passés à la fonction de dessin d'un rectangle, voir paragraphe 2.3.3.

L'intérêt principal d'une telle définition est que l'on va pouvoir obtenir directement, c'est-à-dire sans calculs de notre part, toutes les propriétés d'un rectangle. On utilisera pour cela une syntaxe de la forme :

monRectangle.valeur

L'attribut valeur pourra être : x, y, top, left, bottom, right, topleft, bottomleft, topright, bottomright, midtop, midleft, midbottom, midright, center, centerx, centery, size, width, height.

[Note]

Nous ne détaillerons pas un par un les attributs précédents, les noms étant transparents.

On pourra également se servir de ces attributs pour changer les caractéristiques d'un rectangle.

Example 1.2. Définition et manipulation d'un rectangle

On définit un rectangle, puis on le repositionne en utilisant son attribut bottomright :

>>> import pygame
>>> monRectangle = pygame.Rect(20,10,200,100)
>>> monRectangle.topleft
(20, 10)
>>> monRectangle.bottomright = (250,150)
>>> monRectangle.topleft
(50, 50)
>>> monRectangle.center
(150, 100)
>>> monRectangle.size
(200, 100)

[Note]

Un tel objet peut également être passé en paramètre aux fonctions de dessins des rectangles et ellipses.

Dans ce cours on se servira essentiellement de cette définition pour écrire du texte sur une fenêtre graphique, voir sous-partie 2.6.

Afficher une image

Avant de procéder à un affichage, il faut commencer par charger en mémoire l'image en question :

monImage = pygame.image.load('nom.xxx')

L’image doit se trouver dans le répertoire du programme (sinon on précise son emplacement) et doit être aux extensions classiques : JPG, PNG, GIF, BMP.

[Note]

La commande précédente ne modifie en rien la surface courante.

Une fois l'image chargée, on peut alors la coller sur notre surface :

maSurface.blit(monImage,(x,y))

Cette commande positionnera le coin en haut à gauche de l’image en x y .

Example 1.3. Affichages d'images

Imaginons que nous disposions des deux images suivantes :

  • une photo de Paris (prise depuis les locaux de notre partenaire Learning Tree International) au format jpg, de 660 pixels de largeur et 440 pixels de hauteur, appelée "Fond.jpg" :

  • le logo de SUPINFO au format png, avec de la transparence, de 100 pixels de largeur et 97 pixels de hauteur, appelé "Logo.png" :

Dans le code suivant, on charge la première image en fond puis on lui superpose la seconde :

import pygame
from pygame.locals import *
pygame.init()
maSurface = pygame.display.set_mode((660, 440))
pygame.display.set_caption('Hello SUPINFO')
fond = pygame.image.load("Paris.jpg")
maSurface.blit(fond,(0,0))
sprite = pygame.image.load('Logo.png')
maSurface.blit(sprite,(500,50))
inProgress = True
while inProgress:
    for event in pygame.event.get():
        if event.type == QUIT:
            inProgress = False
    pygame.display.update()
pygame.quit()

En voici le résultat :


[Note]

Le lecteur pourra tester le code précédent en enregistrant les images d'un simple clic-droit. Qu'il n'hésite pas non plus à manipuler ses propres images.

L'illusion du mouvement

On cherche ici à simuler le déplacement d'une image A par rapport à une image de fond B. Imaginons qu'à un moment donné, A ait une certaine position relativement à B. Si l'on veut déplacer A, il suffit alors de recoller dans un premier temps B en fond, puis A à une position différente de celle qu'elle occupait auparavant. On aura l'impression que le fond B est immobile et que l'image A s'est déplacé entre ses deux positions.

Pour régler la vitesse d'un tel déplacement, on fixera la valeur du FPS, Frame Per Second, qui représente le nombre d’images que le programme dessine par seconde. Si on ne le fait pas, le programme ira aussi vite que le permet le processeur. Ce qui peut rendre les jeux et/ou animations trop rapides.

Pour contrôler le FPS avec Pygame, on devra d'abord au début du code initialiser une pendule :

fpsClock = pygame.time.Clock()

A la fin de la boucle de jeu, après la mise à jour de la surface, on utilisera la commande tick :

fpsClock.tick(FPS)

Ici FPS est une constante préalablement définie qui va représenter la limite au nombre d'images que le programme affichera par seconde. La commande tick va imposer au programme de ne pas dépasser cette fréquence et le ralentira si besoin est.

Example 1.4. Déplacement d'une image par rapport à un fond

On reprend les mêmes images que dans l'exemple précédent. Avec une fréquence contrôlée par la constante FPS, on va faire se déplacer l'image "Logo" de droite à gauche, en décrementant son abscisse de 5 pixels à chaque itération :

import pygame
from pygame.locals import *
pygame.init()
FPS = 30
fpsClock = pygame.time.Clock()
maSurface = pygame.display.set_mode((660, 440))
pygame.display.set_caption('Hello SUPINFO')
fond = pygame.image.load("Paris.jpg")
maSurface.blit(fond,(0,0))
sprite = pygame.image.load('Logo.png')
x = 560
inProgress = True
while inProgress:
    maSurface.blit(fond,(0,0))
    x -= 5
    maSurface.blit(sprite,(x,50))
    for event in pygame.event.get():
        if event.type == QUIT:
            inProgress = False
    pygame.display.update()
    fpsClock.tick(FPS)
pygame.quit()

[Note]

Le lecteur est invité à tester ce code avec différentes valeurs pour la constante FPS.

Ecrire du texte

L'écriture d'un texte sur une fenêtre graphique n'est pas aussi simple qu'en mode console où l'on utilisait la commande print.

On doit dans un premier temps sélectionner une police de caractères et une taille d'écriture. On peut utiliser soit les polices du système sur lequel on travaille, soit une police que l'on charge spécifiquement.

Voici comment sélectionner une des polices du système :

maPolice = pygame.font.SysFont('nomDeLaPolice',tailleDeLaPolice)
[Note]

A noter que si la police n'est pas trouvée, il sera utilisé celle par défaut de Pygame.

On peut consulter la liste de toutes les polices disponibles sur le système courant avec la commande :

pygame.font.get_fonts()

Voici maintenant comment charger spécifiquement une nouvelle police située dans le répertoire du projet :

maPolice = pygame.font.Font('nomDeLaPolice.ttf',tailleDeLaPolice)
[Note]

Comme toujours dans ce genre de situation, si la police n'est pas dans le répertoire courant on doit préciser son emplacement.

Le texte que l'on va afficher sera nécessairement encadré par un rectangle. On pourra choisir la couleur de fond de celui-ci et bien sûr celle de l'écriture. Ce rectangle sera automatiquement dimensionné en fonction du texte et de la taille de la police.

Avec la commande render, on va définir la surface contenant notre texte et choisir les couleurs :

maSurfaceDeTexte = fontObj.render(monTexte,lisse,couleurEcriture,couleurFond=None)

L'on constate que le paramètre déterminant la couleur de fond a pour valeur par défaut None, ce qui correspond à un fond transparent.

Le second paramètre est un booléen indiquant si les contours des caractères seront lisses ou non. On le passera à True la majorité du temps.

Une fois cette surface définie, on devra récupérer le rectangle sur lequel elle repose :

monRectangleDeTexte = maSurfaceDeTexte.get_rect()

Il faudra ensuite positionner ce rectangle, par exemple en fixant les coordonnées de son coin supérieur gauche :

monRectangleDeTexte.topleft = (x,y)

Dernière étape, il faudra coller la surface du texte sur le rectangle précédemment positionné :

maSurface.blit(maSurfaceDeTexte,monRectangleDeTexte)

Pour cette dernière étape on a supposé que l'on disposait d'une fenêtre graphique définie auparavant, appelée maSurface.

Example 1.5. Utilisation d'une des polices du système

On reprend ici comme image de fond la photo de Paris utilisée dans les sous-parties précédentes. On utilise la police calibri du système, et on écrit notre texte en noir sur un fond transparent :

import pygame
from pygame.locals import *
pygame.init()
maSurface = pygame.display.set_mode((660, 440))
pygame.display.set_caption('Hello SUPINFO')
BLACK = (0,0,0)
fond = pygame.image.load("Paris.jpg")
maSurface.blit(fond,(0,0))
fontObj = pygame.font.SysFont('calibri',40)
maSurfaceDeTexte = fontObj.render('Paris, Ville Lumière',True,BLACK)
monRectangleDeTexte  = maSurfaceDeTexte.get_rect()
monRectangleDeTexte .topleft = (175,50)
maSurface.blit(maSurfaceDeTexte,monRectangleDeTexte)
inProgress = True
while inProgress:
    for event in pygame.event.get():
        if event.type == QUIT:
            inProgress = False
    pygame.display.update()
pygame.quit()

Que le lecteur prenne bien le temps d'identifier et comprendre les différentes étapes.

Voici le résultat de l'exécution de ce code :


Example 1.6. Utilisation d'une police spécifique

Toujours avec le même fond, on charge ici la police "Les Hommes Dansants" présente dans le répertoire de notre script. On écrit cette fois-ci en blanc sur fond noir :

import pygame
from pygame.locals import *
pygame.init()
maSurface = pygame.display.set_mode((660, 440))
pygame.display.set_caption('Hello SUPINFO')
WHITE = (255,255,255)
BLACK = (0,0,0)
fond = pygame.image.load("Paris.jpg")
maSurface.blit(fond,(0,0))
fontObj = pygame.font.Font('Les-Hommes-Dansants.ttf',40)
maSurfaceDeTexte = fontObj.render('Paris, Ville Lumiere',True,WHITE,BLACK)
monRectangleDeTexte  = maSurfaceDeTexte.get_rect()
monRectangleDeTexte .topleft = (125,50)
maSurface.blit(maSurfaceDeTexte,monRectangleDeTexte )
inProgress = True
while inProgress:
    for event in pygame.event.get():
        if event.type == QUIT:
            inProgress = False
    pygame.display.update()
pygame.quit()

Et voici ce que produit ce code :


[Note]

Le lecteur trouvera ici la police bien particulière de l'exemple précédent. Elle est issue de la célèbre nouvelle éponyme des aventures de Sherlock Holmes, écrite par Arthur Conan Doyle.

Gestion des événements

Dans cette partie, nous allons apprendre à réceptionner des événements du clavier et de la souris.

Evénements du clavier

Les premiers tests à connaître sont ceux permettant de détecter l'appui ou le relachement d'une touche.

Voilà comment tester si une touche a été appuyée :

if event.type == KEYDOWN

Et voici la condition pour vérifier si une touche a été relachée :

if event.type == KEYUP

Il faut bien comprendre que les tests précédents sont indépendants de la touche pressée ou relachée. C'est pourquoi on les complète en général par une vérification de la valeur de cette touche.

Pour faire cela, on récupère la valeur d'une touche (pressée ou relachée) avec la commande key et on la compare avec des constantes identifiant les différentes touches du clavier. En voici certaines :

  • Constantes associées aux touches alphabétiques : K_a, K_b, ..., K_z

  • Constantes associées aux touches numériques : K_0, ..., K_9

  • Constantes associées à certaines touches spéciales : K_SPACE, K_RIGHT, K_LEFT, K_DOWN, K_UP

[Note]

Pour une liste exhaustive des constantes associées par Pygame aux touches d'un clavier, voir ici.

Example 1.7. Déplacement d'une image avec les flêches du clavier

On reprend les images de la partie précédente. Dès que l'utilisateur appuiera sur la flêche gauche ou sur la flêche droite, l'image "Logo" se décalera de 5 pixels dans cette direction :

import pygame
from pygame.locals import *
pygame.init()
maSurface = pygame.display.set_mode((660, 440))
pygame.display.set_caption('Hello SUPINFO')
fond = pygame.image.load("Paris.jpg")
sprite = pygame.image.load('Logo.png')
x = 300
inProgress = True
while inProgress:
    for event in pygame.event.get():
        if event.type == QUIT:
            inProgress = False
        if event.type == KEYDOWN:
            if event.key == K_LEFT:
                x -= 5
            if event.key == K_RIGHT:
                x += 5
    maSurface.blit(fond,(0,0))
    maSurface.blit(sprite,(x,50))
    pygame.display.update()
pygame.quit()

[Note]

Pour gérer les répétitions d'événements lorsqu’on laisse une touche appuyée, on utilisera cette commande en amont de la boucle de jeu :

pygame.key.set_repeat(t1,t2)

Le premier paramètre représente le délai avant le déclenchement de la première répétition, et le second mesure l’intervalle de temps entre les répétitions suivantes. Ces durées sont exprimées en millisecondes.

Evénements de la souris

Comme pour le clavier avec les touches, on devra d'abord apprendre à tester le clic ou le relachement de la souris.

Voici comment vérifier qu'un clic a été effectué :

if event.type == MOUSEBUTTONUP

Quand au relachement de la souris, on le détectera avec :

if event.type == MOUSEBUTTONDOWN

Il sera ensuite très utile de pouvoir récupérer les coordonnées de la souris lors d'un clic ou d'un relachement. On utilisera pour cela la fonction pos qui retournera un t-uple avec ces coordonnées.

On pourra alors effectuer une affectation multiple :

positionX, positionY = event.pos

Il sera également possible de manipuler directement les deux éléments de ce t-uple :

event.pos[0], event.pos[1]

Enfin, si cela est utile, on pourra distinguer les différents types de clics avec la fonction button. Celle-ci retourne un entier compris entre 1 et 5 qui correspond à :

  • 1 : bouton gauche

  • 2 : bouton du milieu

  • 3 : bouton droit

  • 4 : molette haut

  • 5 : molette bas

Example 1.8. Déplacement d'une image avec la souris :

On reprend les images de la partie précédente. Dès que l'utilisateur cliquera à un endroit donné de la fenêtre, le coin en haut à gauche de l'image "Logo" se positionnera à cet endroit :

import pygame
from pygame.locals import *
pygame.init()
maSurface = pygame.display.set_mode((660, 440))
pygame.display.set_caption('Hello SUPINFO')
fond = pygame.image.load("Paris.jpg")
sprite = pygame.image.load('Logo.png')
maSurface.blit(fond,(0,0))
maSurface.blit(sprite,(300,50))
inProgress = True
while inProgress:
    for event in pygame.event.get():
        if event.type == QUIT:
            inProgress = False
        if event.type == MOUSEBUTTONUP:
            x,y = event.pos
            maSurface.blit(fond,(0,0))
            maSurface.blit(sprite,(x,y))
    pygame.display.update()
pygame.quit()

A propos de SUPINFO | Contacts & adresses | Enseigner à SUPINFO | Presse | Conditions d'utilisation & Copyright | Respect de la vie privée | Investir
Logo de la société Cisco, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société IBM, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Sun-Oracle, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Apple, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Sybase, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Novell, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Intel, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Accenture, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société SAP, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Prometric, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo du IT Academy Program par Microsoft, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management

SUPINFO International University
Ecole d'Informatique - IT School
École Supérieure d'Informatique de Paris, leader en France
La Grande Ecole de l'informatique, du numérique et du management
Fondée en 1965, reconnue par l'État. Titre Bac+5 certifié au niveau I.
SUPINFO International University is globally operated by EDUCINVEST Belgium - Avenue Louise, 534 - 1050 Brussels