Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • rvuillem/INF-TC2
  • teixeira/INF-TC2
  • mdemeill/INF-TC2
  • epelous/INF-TC2
  • rgayet/INF-TC2
  • gparamuc/INF-TC2
  • pdewilde/INF-TC2
  • bnegre/INF-TC2
  • elichiya/INF-TC2
  • amacgreg/INF-TC2
  • yjaid/INF-TC2
  • lcholley/INF-TC2
  • hwei/INF-TC2
  • lmelodef/INF-TC2
  • mnauche/INF-TC2
  • nbernier/INF-TC2
  • gbouvier/INF-TC2
  • lalbin/INF-TC2
  • jdelaffo/INF-TC2
  • ndjaoud/INF-TC2
20 results
Select Git revision
Show changes
Showing
with 1551 additions and 0 deletions
seance3_4h/figures/schema_bdd_hotellerie.png

26.2 KiB

File added
**Sommaire**
[[_TOC_]]
# BE #3 : Exceptions et Base de données SQL
L'objectif principal de ce BE concerne l'utilisation **des exceptions** ([lien](https://docs.python.org/fr/3/tutorial/errors.html) officiel, [tuto _devstory_](https://devstory.net/11421/python-exception-handling) sur les exceptions) pour améliorer la robustesse d'un code. Pour expérimenter ce concept clé, nous nous servirons du prétexte de la manipulation de bases de données à l'aide de requêtes _SQL_ (_Structured Query Language_), écrites en _Python_. Ce BE est composé de trois parties :
1. **La première partie** (durée: 45 min.) présente quelques commandes élémentaires pour interroger une base _SQL_ à partir de _Python_;
1. **La seconde partie** (durée: 75 min.) permet de découvrir comment manipuler une base de données _SQL_ en _Python_ orienté objet.
1. **La troisième partie** (durée: 120 min. et +) vous engage dans un travail plus personnalisé, pour mettre à profit vos connaissances sur la gestion des exceptions, la librairie graphique *matplotlib* et le langage d'interrogation de bases _SQL_.
Ce BE fera l'objet d'un compte-rendu (CR), seul ou en binôme. Avant de commencer, veuillez prendre connaissance des consignes concernant le rendu du travail (à respecter scrupuleusement) qui se trouvent dans le fichier [consignes_BE#3.md](./consignes_BE#3.md) (dans le même répertoire que cet énoncé). Les critères de notation y sont présentés.
---
## 1. Mini-tutoriel sur la base Hotellerie.db (45 min.)
Le système de gestion de base de données (SGBD) qui sera utilisé durant ce BE est _SQLite_. Ce système stocke une base de données dans un fichier d'extension _.sqlite_. La base de tests que nous allons utiliser dans cette partie (_hotellerie.db_) est disponible au même endroit que cet énoncé. Son schéma est le suivant :
<center><img src="figures/schema_bdd_hotellerie.png" style="width:70%"/></center>
La base est composée de 5 tables, ces tables étant composées d'un nombre variable de champs. Les champs soulignés représentent les clés primaires (ou *primary key (PK)* en anglais) de chaque table. En particulier, la clé primaire de la table **chambre** est composée des attributs *numchambre* et *numhotel* (cette dernière étant la clé primaire de la table **hotel**).
*Remarque* : Vous trouverez [ici](https://www.youtube.com/watch?v=VgTRNqn2fn0) une vidéo qui montre comment utiliser [draw.io](https://app.diagrams.net) pour créer un diagramme entité-association. Il NE vous est PAS demandé de dessiner le diagramme de cette base de données.
### 1.1 DB browser for SQLite (15 min.)
Toutes les opérations sur une base de données de ce type peuvent être effectuées en _Python_ via les classes et les méthodes présentes au sein du module _sqlite3_ ([doc officielle de la librairie](https://docs.python.org/3/library/sqlite3.html)). Pour manipuler de manière interactive le contenu de la base (créer, supprimer ou modifier des tables et des enregistrements, effectuer des requêtes _SQL_...), il existe des outils adaptés. L'outil retenu dans le cadre de ce BE s'appelle ``DB Browser for SQLite``. C'est un logiciel libre qui existe pour toutes les plate-formes : _Windows_, _MacOs_, nombreuses distributions _Linux_ et _Unix_...
- Téléchargez et installez [DB Browser for SQLite](https://sqlitebrowser.org/) en suivant les instructions d'installation adaptées à votre système d'exploitation.
- Avec ce logiciel, ouvrez la base *hotellerie.db* et naviguez dans les tables (onglet `Structure de la Base de Données`) et les enregistrements (onglet `Parcourir les données`) pour prendre connaissance de la base (telle qu'elle est schématisée ci-dessus).
<center><img src="figures/DBBrowser.png" style="width:75%"/></center>
- Dans l'onglet `Exécuter le SQL`, lancez la requête suivante
```SQL
SELECT nom, ville
FROM hotel;
```
La réponse apparaît sous forme de 12 lignes. Ça vous rappelle des choses ? Si non, alors voici quelques pointeurs pour vous rafraîchir la mémoire
- [cours tutoriel sur SQL](https://www.1keydata.com/fr/sql/)
- [SQL : sélection, jointure, regroupement, filtre](http://cerig.pagora.grenoble-inp.fr/tutoriel/bases-de-donnees/chap20.htm)
- et tant d'autres...
### 1.2 Quelques requêtes en _Python_ (15 min.)
**Attention** Avant de lancer un requête sur la bdd avec _Python_, il est fortement conseillé de fermer `DB Browser for SQLite`, sinon vous pourriez soit avoir un plantage de votre programme, soit détruire la bdd (auquel cas il vous suffirait de la télécharger à nouveau depuis ce site Web).
Nous allons à présent chercher à reproduire la requête ci-dessus en utilisant _Python_ et le package _sqlite3_. C'est une librairie objet dont la [documentation](https://docs.python.org/3/library/sqlite3.html#module-sqlite3) fournit une description des classes et des méthodes disponibles. Suivez le guide...
Le squelette typique d'un tel programme s'écrit :
```python
import sqlite3
if __name__ == '__main__':
conn = sqlite3.connect('hotellerie.db') # connexion à la bdd
# travail sur la bdd à partir du connecteur
...
conn.commit() # pour enregistrer les éventuels changements
conn.close() # pour fermer proprement l'accès à la base
```
Voici le code _Python_ permettant d'obtenir la réponse à la requête précédente :
```python
import sqlite3
if __name__ == '__main__':
conn = sqlite3.connect('hotellerie.db')
curseur = conn.cursor() # objet permettant de faire des requêtes
curseur.execute("SELECT nom, ville FROM hotel;") # requête SQL
ligne1 = curseur.fetchone() # récupère la 1ère ligne du résultat de la requête
print('ligne1 =', ligne1)
ligneAll = curseur.fetchall() # récupère toutes les lignes suivantes
print('ligneAll =', ligneAll)
conn.close()
```
_Remarques_
- La commande `conn.commit()` n'est pas nécessaire ici puisque le script est une requête en lecture ; elle ne modifie donc pas la bdd.
- Notez que la méthode `fetchone()` retire le résultat de la liste des résultats. Pour preuve: ce résultat n'est pas présent suite à l’affichage du `fetchall()`.
Copiez et exécutez ce programme ; le résultat se présente sous forme d'un tuple, ou sous forme d'une liste de tuples. Ainsi la commande suivante imprime le nom du premier hôtel qui apparaît dans la liste des résultats de la requête :
```python
print(ligneAll[0][0])
```
Voici un usage intéressant à tester :
```python
import sqlite3
if __name__ == '__main__':
conn = sqlite3.connect('hotellerie.db')
curseur = conn.cursor()
for ligne in curseur.execute("SELECT * FROM hotel WHERE etoiles=3"):
print('ligne=', ligne)
conn.close()
```
### 1.3 La gestion des exceptions (15 min.)
Les quelques lignes de code précédentes peuvent être à l'origine de nombreux problèmes lors de l'exécution :
- la base de données est introuvable;
- les noms des tables et/ou des champs dans la requête sont erronés;
- ...
Voyons maintenant comment intercepter les exceptions lancées dans ces cas de figure par les méthodes de la librairie `sqlite3`. Pour cela, veuillez d'abord copier et exécuter le programme suivant :
```python
import sqlite3
if __name__ == '__main__':
try:
conn = sqlite3.connect('hotellerie.db')
curseur = conn.cursor()
curseur.execute("SELECT nom, ville FROM hotel;")
print(curseur.fetchall())
except Exception as err: # interception d'une exception quelconque
print('err:', str(err))
print('type exception:', type(err).__name__)
finally: # fermeture de la base dans tous les cas
conn.close()
```
A priori, ce programme ne lance pas d'exception. Modifiez-le pour faire apparaître les 2 problèmes énoncés ci-dessus. Pour cela :
- Changez le nom de la bdd dans le programme, p. ex. _impossible.db_. Comment interprétez-vous le message d'erreur en observant le contenu de votre répertoire de travail ?
- Revenez au nom correct du fichier : _hotellerie.db_. Testez alors des noms erronés pour les tables, puis pour les champs.
On constate, dans chaque situation, que l'exception `sqlite3.OperationalError` est lancée, avec des messages d'information différents qui précisent le type d'erreur. Remplacez alors le code `except Exception as err:` par le code `except sqlite3.OperationalError as err:`, et vérifiez que cela fonctionne de la même manière que précédemment.
La liste des exceptions lancées par l'usage de commandes `sqlite3` est disponible en suivant [ce lien](https://docs.python.org/3/library/sqlite3.html#exceptions). Prenez le temps de lire la description des différentes exceptions. Toutes les exceptions de ce module héritent d'une classe appelée __sqlite3.Error__ (elle-même héritant de la classe de base de gestion des exceptions de _Python_ : __Exception__).
---
## 2. Classe HotelDB (75 min.)
Dans cette partie, nous allons créer un classe **HotelDB** permettant de réaliser des requêtes de lecture et de mises à jour de la base *Hotellerie.db*.
### 2.1 Requête en lecture (30 min.)
Dans un fichier *HotelDB.py*, commencez à développer la classe permettant de répondre au programme principal suivant, dont l'objectif est d'afficher le nom des hôtels 2 étoiles (notez que le nombre d'étoiles est passé en argument) :
```python
if __name__ == '__main__':
aHotelDB = HotelDB('hotellerie.db')
nbEtoiles = 2
resultat = aHotelDB.get_name_hotel_etoile(nbEtoiles)
print("Liste des noms d'hotel", nbEtoiles, "étoiles : ", resultat)
```
Le constructeur (méthode *\_\_init\_\_(...)*) se chargera d'ouvrir une connexion vers la bdd, alors que le destructeur (méthode *\_\_del\_\_(...)*, _cf_ remarque ci-dessous) se chargera de la fermer.
_Remarques_ :
- Pour fermer correctement l'accès à la base de donnée, pensez à implémenter la méthode *\_\_del\_\_(...)* (vue en cours), qui est appelée automatiquement (et de manière implicite) par _Python_ lors de la destruction des objets de la classe. Typiquement :
```python
def __del__ (self):
self.__conn.close()
```
- La méthode `get_name_hotel_etoile(...)` se charge de retourner le résultat de la requête, mais ne se charge pas d'en afficher le résultat. L'affichage est laissé au programme principal, ici essentiellement pour contrôler le résultat.
- Pensez à intercepter les exceptions de type `sqlite3.OperationalError`, comme vu précédemment, et à renvoyer dans ce cas un résultat sous la forme d'une liste vide.
__Améliorations à implémenter__ :
- Comment se comporte votre programme si on insère cet appel `aHotelDB.get_name_hotel_etoile(-1)` dans le programme principal ? **Truc:** exception standard **ValueError** ou **AssertionError**.
- Comment se comporte votre programme si on insère cet appel `aHotelDB.get_name_hotel_etoile("Hello")` ? **Truc:** exception standard **TypeError**.
Veillez à ce que ces _appels erronés_ renvoient une liste vide tout simplement.
### 2.2 Requête en écriture (45 min.)
Créer une requête permettant d'ajouter un nouveau client et de renvoyer son identifiant (c'est à dire son _numclient_). Si le client existe déjà (même nom ET même prénom), la méthode renverra son _numclient_ (on supposera qu'il n'y a pas clients homonymes). Pour cette requête, renseignez-vous sur la commande `INSERT INTO`. _Attention_ la clé primaire sera renseignée automatiquement, pas besoin de la préciser explicitement. Notez également que l'attribut _curseur.lastrowid_ permet de récupérer le _numclient_ du nouveau client.
Vérifier que le nouveau client a bien été sauvegardé dans le fichier *Hotellerie.db* :
- soit en consultant la base avec `DB Browser for SQLite`;
- soit en exécutant par 2 fois successives le même programme ; vous devriez alors retrouver le même numéro de client.
_Remarques_ :
- Pensez à quitter le logiciel `DB Browser for SQLite` avant d'exécuter votre programme.
- En cas de destruction de la base `Hotellerie.db` (les requêtes en écriture sont toujours plus dangereuses que les requêtes en lecture !), pensez à la télécharger à nouveau !
---
## 3. Requêtes libres (120 min. et +)
Dans cette dernière partie, nous vous invitons à imaginer et implémenter **DEUX (2)** requêtes originales à partir de la bdd *Hotellerie.db*, ou de tout autre bdd que vous aurez trouvée sur Internet.
Les résultats de vos requêtes devront faire l'objet d'une représentation graphique (graphe, histogramme, camembert...) en utilisant la librairie _Matplotlib_ (cf remarques ci-dessous).
Vous pouvez _justifier_ la robustesse de vos requêtes en écrivant, dans votre programme principal, plusieurs appels à vos requêtes avec des paramètres farfelus, erronés... Bonus à ceux qui développerons une exception propre !
### Liens vers quelques Bdds `sqlite`
Voici quelques exemples de sites proposant des bdd _SQLite_ gratuites :
> - Une base de données de films est téléchargeable en suivant [ce lien](https://1drv.ms/u/s!Ap1xZ3X70U50gvdIaHBrQ5uvSD-WSg?e=ncEblG). Elle est composée de 4 tables (acteur, réalisateur, film, distribution)
> - Le site [SQLite tutorial](https://www.sqlitetutorial.net/sqlite-sample-database/) propose un base de données appelée _chinook_ (_digital media store_), composée de 11 tables
> - Dans le même genre, une base de données très célèbre : [Northwind](https://cs.ulb.ac.be/public/_media/teaching/infoh303/northwind_sqlite.db.zip) (8 tables)
> - Si vous êtes fan des _Pokémon_, vous pouvez décompresser la base [veekun's Pokédex](http://veekun.com/static/pokedex/downloads/veekun-pokedex.sqlite.gz) (172 tables !)
> - Si vous êtes fan de musique, vous pouvez décompresser et utiliser la base [musicBrainz](https://matthieu-moy.fr/cours/infocpp-S3/TPL/musicBrainz.zip) (4 tables)
> - Une petite base concernant la [peinture](https://carnot.cpge.info/wp-content/uploads/2020/02/peinture.db)
> - Beaucoup plus complexe : [murder-mystery](https://forge.univ-lyon1.fr/diu-eil/bloc4/-/raw/master/3_bases_de_donnees_introduction/TP/base-sql-murder-mystery.db) (9 tables). Lire le [site original](https://github.com/NUKnightLab/sql-mysteries)
> - [Postuler à Stanford](https://forge.univ-lyon1.fr/diu-eil/bloc4/-/raw/master/3_bases_de_donnees_introduction/TP/base-stanford.db) (3 tables).
Vous pouvez également transformer des données du format `.csv` (_Comma Separated Value_) vers le format `.sqlite3`, en suivant ce [tutoriel vidéo](https://tube.ac-lyon.fr/videos/watch/85399ea5-bba0-428b-9470-2d3bb41b7de1). Toutes les données _open data_ de [data.gouv.fr](https://www.data.gouv.fr/fr/), par exemple, deviennent alors exploitables pour votre CR...
Au cas où vous opteriez pour une bdd originale, n'oubliez pas d'inclure cette base dans votre archive (si elle n'est pas trop volumineuse), et de préciser dans votre rapport le chemin pour la télécharger.
### Quelques conseils
Les deux requêtes attendues doivent être relativement sophistiquées (pas de simples `select XX from YY`).
> - Si vous optez pour la bdd `Hotellerie.db`, n'hésitez pas à visiter un site de réservation d'hôtels pour trouver des idées de requêtes intéressantes. _Attention_ : le nom d'un hôtel n'est pas une clé primaire ! Plusieurs hôtels portent le même nom. Par contre, il n'existe pas 2 hôtels de même nom dans la même ville. Pensez-y !
> - Si vous optez pour une autre base, développez une seconde classe dans un second fichier indépendant (sur le modèle de la classe **HotelDB**).
**Remarques** :
> - Vous programmerez les représentations graphiques dans le programme principal (et non pas dans la méthode qui traite la requête). En effet, quand on fait une requête sur une base de données, l'affichage graphique ne doit pas être obligatoire. C'est pour cela qu'on sépare la requête de l'affichage de son résultat (qu'il soit au format texte ou au format graphique).
> - Usage de _Matplotlib_ : À titre d'exemples, vous trouverez, à côté de cet énoncé, un fichier nommé [ex_matplotlib.py](./ex_matplotlib.py). L'exécution de ce script génère 4 figures dans le sous-répertoire *figures*. Inspirez-vous largement de ce programme pour vos propres figures.
> - *Conseil*: Évitez de vous lancer dans des requêtes avec des données géographiques, genre `trouver tous les hôtels à moins de 5 kilomètres` car l'usage de cartes géographiques dépasse les attentes de ce qui est demandé ici.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="298px" height="183px" viewBox="-0.5 -0.5 298 183" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2020-10-01T11:54:44.123Z&quot; agent=&quot;5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36&quot; etag=&quot;epBQuWO_AHDW0usSiURE&quot; version=&quot;13.7.7&quot; type=&quot;device&quot;&gt;&lt;diagram name=&quot;Page-1&quot; id=&quot;c4acf3e9-155e-7222-9cf6-157b1a14988f&quot;&gt;7VjbctowEP0aHmGMjGzzyCWXziRtMuk0IW+yLdtqhEWFIJCvr4RlbOFwCRDStH1htEfWSjp7tFpUs3vD2QVHo+SahZjWgBXOana/BoDrOfJXAfMMgMDOgJiTMIOsArgjLzgDmzk6ISEeayyDBGNUkJEJBixNcSAMDHHOns3PIkZDAxihGFeAuwDRKnpPQpFkqAfcAr/EJE7ymZtOO+vxUfAUczZJ9XwpS3HWM0S5G73HcYJC9lyC7LOa3eOMiaw1nPUwVayajJ2v6V0umeNU7DLgW3d2Mej3O+DL9PJh0KH864DWQUsvTsxzLnAoqdEmpj57PiuA7mKrWHm0pMW4SFjMUkSvGBtJsCnBn1iIuQ4xmggmoYUbaU4xF0SyLqFEDKkegGdEPCiPDRdqc6AnUO3+rGzMcyMNOyrw0gwJGjIVAAWeE5r7HQvOnpbxbEmkSplmUe25BGgCLzAbYsHn8gOOKRJkasoFadXFy++WQ28YkVMASx8Q24YNmA3SJwTYlulkzCY8wHpcOYxvdyUQj7GouJKN0p4KaKGTt2gG/kGa+UsFA6BzHLlsdXQ8sbjn93HyeB+A5JrDyY34UXfH9WZ7o1gKNRyumLI8Urnqh7KxEEgD5mahkYWVi2Qs2RDaq7zC9lANUGubDEfaibdOqw24Ua1rhZfFPYNm3QDz6EZckQ5o33b82193rN7U8c7iuulD94Ok7Lb2k3Iz15J2ZOeX8ImkrFyq6aaITkwyVsR9hXy8kq8QJXEq24GMJ+YSyNNaR3cMSRhm2sdj8oL8hT+lhJHazmKDsFuD/Ve1sfHkqZnwzFivLqP0LEY9YkRej5IXs+2YQdSO9pWG9uKaA1gUjfH7hM7+R0NXtxpey3UPi1buCxgSaL9D8F5NVNVjVw1dkaZ9yoKnLEnrHNw2Ura15qYoXQ6Dct+am6IoWnevWQ9I6u6uSR3umNSfi785Tcc6ij4AWMkRDtwv0dveFkfHS/Svktj6L7jdqwjv4wRnW2ZBsHeRDL3Wyn+qU0suP7eG5hwqme/6shGrxvenHJJTLNGKNEtai6QCe4wyvuixIy/AQbAsWUs9vgdbcKNiKlfR2ivHNQ8v1AIpxT+v25LSkwqA66NvkP1mZp3tzD6yFHeiiASJeic6kOQoAq+THDq+I2vho5AsaV1VLHQrRDct65RMu9uZPsfpDSdpQEbq7e0zMO2ArTS33VOy7G1nuYfSqZz4M2SL5b/Bd08X0iweW7O8Xbxl22e/AQ==&lt;/diagram&gt;&lt;/mxfile&gt;"><defs/><g><path d="M 273.5 172 L 273.5 172 L 273.5 172" fill="none" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 273.5 172 L 273.5 172 L 273.5 172 L 273.5 172 Z" fill="#000000" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 194 172 L 194 172 L 194 172" fill="none" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 194 172 L 194 172 L 194 172 L 194 172 Z" fill="#000000" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 196.5 111.5 L 106.41 111.5" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 98.41 111.5 L 102.41 107.5 L 106.41 111.5 L 102.41 115.5 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 120px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">1</div></div></div></foreignObject><text x="111" y="123" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">1</text></switch></g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 121px; margin-left: 187px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">1</div></div></div></foreignObject><text x="187" y="124" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">1</text></switch></g><path d="M 48.5 99 L 48.5 36.12" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 48.5 26.12 L 53.5 36.12 L 43.5 36.12 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 246.5 99 L 246.5 36.12" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 246.5 26.12 L 251.5 36.12 L 241.5 36.12 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="14" y="0" width="69" height="25" fill="#f8cecc" stroke="#b85450" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 13px; margin-left: 49px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><b>Tk</b></div></div></div></foreignObject><text x="49" y="16" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Tk</text></switch></g><rect x="196.5" y="99" width="100" height="25" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 112px; margin-left: 247px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><b>ZoneAffichage</b></div></div></div></foreignObject><text x="247" y="115" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">ZoneAffichage</text></switch></g><rect x="0" y="99" width="97" height="25" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 112px; margin-left: 49px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><b>FenPrincipale</b></div></div></div></foreignObject><text x="49" y="115" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">FenPrincipale</text></switch></g><rect x="212" y="0" width="69" height="25" fill="#f8cecc" stroke="#b85450" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 13px; margin-left: 247px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><b>Canvas</b></div></div></div></foreignObject><text x="247" y="16" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Canvas</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://desk.draw.io/support/solutions/articles/16000042487" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="544px" height="183px" viewBox="-0.5 -0.5 544 183" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2020-10-01T12:24:19.841Z&quot; agent=&quot;5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36&quot; etag=&quot;7_P7bSVEtSraPxa-TKuH&quot; version=&quot;13.7.7&quot; type=&quot;device&quot;&gt;&lt;diagram name=&quot;Page-1&quot; id=&quot;c4acf3e9-155e-7222-9cf6-157b1a14988f&quot;&gt;7VpZc6M4EP41fpkqu7iPRx9JJluZmWQzu4nnDYM4NoC8Qr7y61cYySCD8Ykdb+bFhT5BC77+utXqckvuR/M7ZI39b9ABYUsSnHlLHrQkSTc08psCiwxQdCUDPBQ4GSTkwHPwDjJQZOgkcEBCsQzCEIY4GPOgDeMY2JjDLITgjL/NhaHDAWPLAyXg2bbCMvoSONjPUEPSc/wrCDyfrSxqZjYzsuw3D8FJTNeLYQyymchiZug3Jr7lwFkBkm9ach9BiLOraN4HYcoqz9jthtnVKyMQ410e+NGb3w0Hg650P/36OuyG6PswbEvUTwleMC6AQ6ihQxCO4OwmB3rLTwWpRYGMIMI+9GBshQ8QjgkoEvAfgPGCutiaYEigpRkynAKEA8I6gXwchfQBMA/wa2qxo6t0OKQLpNeDeXGwYIPY6aaOJ0MnsCKYOiAFb4OQ2U0wgm8rfyoEKVNGWUy/uQBQAu8AjABGC3IDAqGFgykvF4uqzlvdt3r0EQZkCUmgASLLakfNHqIRIskCbySBE2QD+lzRjfubwhbyAC6ZIheFb8qhpU720Yz6gTTzPxWMpGqnkctWQ6cTi3774vm/XmzJ/4bUySP+u60nbdGsFUuuhuMVU5RHTN76tThYCqSjsmGukeWIiSQhbGBqVZIPUY2UvtskGlMjxiatdtRatW4UXub3DJr3bIDcR/wQdCXzqTt6+vcZtkXq78yvdTfqF5Iyqw32lbLItEQNyWwTPpOUU5PpclMrnPBkrIn7wRqBtXxlhYEXk2ub+BMgArC01qUTUeA4mfZBErxbo6W9VAnj9HOWH6j2WuqgUhu1kZeuBObc+9Iyiq7C1SOc5+lTZGOWNd6J1NCh0qBWdP4B6LoJaMZ18id1XVvoGIquH+ctZkviJGA24LzKRFUOu7Lr8jQ9CqH9liVpmoNNLmULG3aKwuYwLM5t2CnyonX3mvWIpK7vmtTVHZP6LD/miJpwEn1I0lqO0NTDEr1sbDF0ukRfSaLyW3C7VxHG5QQnC3xBcHCRrBrK2pnq3JJjcctpTgsJ870RufDSi59vDCJLrNCSNAtac4kC+zCEaDkju4YNbHtVshZmRoaqqLWKKW1FG7ccnQ9elQqk4H9Wt/mFloqkbvY+R/bezGrbmf0FY9B13cD20z7RkSS7rlRNsqONNFILn4RkQuu6YlW9RLQoCOdkWt/O9C2IH1EQ28E47b1dA9OatJVmUz8ny8Z2lvtWPCULX0O2WJ0Gz58uHpDxM/r+4/3ent0/mX+9A+uPXrv6WNBwu6KZtsOBPZDG2hWVfCu71hnajnXGkTWFosh8vBtrJnYuYjV9zVBjjbdKYj9ss6Iu7D5Zr6KSinKrQuh0vnwG311Zs6Iun9XWQBBF11H7KGw3vkSNWUlvVTHfxNFc4s7mwq5bJnc2FxvaMit6QXVSvMTJXGUncSoclpH3PpibpYO53tjBvI7sunj+M01xsXcl5xlFFDlCL11wmxUENxHR+geOaPY3mA8d0gof0vqBIa2YawW2tlZZNRzQjOu6iL4Jw2CcXEc8q/K5+m1kmP9bKXNH/mcw+eY/&lt;/diagram&gt;&lt;/mxfile&gt;"><defs/><g><path d="M 273.5 172 L 273.5 172 L 273.5 172" fill="none" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 273.5 172 L 273.5 172 L 273.5 172 L 273.5 172 Z" fill="#000000" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 194 172 L 194 172 L 194 172" fill="none" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 194 172 L 194 172 L 194 172 L 194 172 Z" fill="#000000" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 196.5 111.5 L 106.41 111.5" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 98.41 111.5 L 102.41 107.5 L 106.41 111.5 L 102.41 115.5 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 120px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">1</div></div></div></foreignObject><text x="111" y="123" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">1</text></switch></g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 121px; margin-left: 187px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">1</div></div></div></foreignObject><text x="187" y="124" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">1</text></switch></g><path d="M 48.5 99 L 48.5 36.12" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 48.5 26.12 L 53.5 36.12 L 43.5 36.12 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 246.5 99 L 246.5 36.12" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 246.5 26.12 L 251.5 36.12 L 241.5 36.12 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="14" y="0" width="69" height="25" fill="#f8cecc" stroke="#b85450" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 13px; margin-left: 49px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><b>Tk</b></div></div></div></foreignObject><text x="49" y="16" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Tk</text></switch></g><rect x="196.5" y="99" width="100" height="25" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 112px; margin-left: 247px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><b>ZoneAffichage</b></div></div></div></foreignObject><text x="247" y="115" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">ZoneAffichage</text></switch></g><rect x="0" y="99" width="97" height="25" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 112px; margin-left: 49px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><b>FenPrincipale</b></div></div></div></foreignObject><text x="49" y="115" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">FenPrincipale</text></switch></g><rect x="212" y="0" width="69" height="25" fill="#f8cecc" stroke="#b85450" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 13px; margin-left: 247px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><b>Canvas</b></div></div></div></foreignObject><text x="247" y="16" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Canvas</text></switch></g><path d="M 396 111.5 L 305.91 111.5" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 297.91 111.5 L 301.91 107.5 L 305.91 111.5 L 301.91 115.5 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 120px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">1</div></div></div></foreignObject><text x="311" y="123" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">1</text></switch></g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 121px; margin-left: 387px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">0..*</div></div></div></foreignObject><text x="387" y="124" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">0..*</text></switch></g><rect x="396" y="99" width="100" height="25" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 112px; margin-left: 446px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><b>Forme</b></div></div></div></foreignObject><text x="446" y="115" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Forme</text></switch></g><path d="M 383.5 25 L 415.97 89.08" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 420.49 98 L 411.51 91.34 L 420.43 86.82 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="349" y="0" width="69" height="25" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 13px; margin-left: 384px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><b>Rectangle</b></div></div></div></foreignObject><text x="384" y="16" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Rectangle</text></switch></g><path d="M 508.5 25 L 476.03 89.08" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 471.51 98 L 471.57 86.82 L 480.49 91.34 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="474" y="0" width="69" height="25" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 13px; margin-left: 509px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><b>Ellipse</b></div></div></div></foreignObject><text x="509" y="16" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Ellipse</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://desk.draw.io/support/solutions/articles/16000042487" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
\ No newline at end of file
seance4_4h/figures/interface.png

8.7 KiB

class Forme:
def __init__(self, canevas, x, y):
self.__canevas = canevas
self._item = None
self.x = x
self.y = y
def effacer(self):
self.__canevas.delete(self._item)
def deplacement(self, dx, dy):
self.__canevas.move(self._item, dx, dy)
self.x += dx
self.y += dy
class Rectangle(Forme):
def __init__(self, canevas, x, y, l, h, couleur):
Forme.__init__(self, canevas, x, y)
self._item = canevas.create_rectangle(x, y, x+l, y+h, fill=couleur)
self.__l = l
self.__h = h
def __str__(self):
return f"Rectangle d'origine {self.x},{self.y} et de dimensions {self.__l}x{self.__h}"
def get_dim(self):
return self.__l, self.__h
def set_dim(self, l, h):
self.__l = l
self.__h = h
def contient_point(self, x, y):
return self.x <= x <= self.x + self.__l and \
self.y <= y <= self.y + self.__h
def redimension_par_points(self, x0, y0, x1, y1):
self.x = min(x0, x1)
self.y = min(y0, y1)
self.__l = abs(x0 - x1)
self.__h = abs(y0 - y1)
class Ellipse(Forme):
def __init__(self, canevas, x, y, rx, ry, couleur):
Forme.__init__(self, canevas, x, y)
self._item = canevas.create_oval(x-rx, y-ry, x+rx, y+ry, fill=couleur)
self.__rx = rx
self.__ry = ry
def __str__(self):
return f"Ellipse de centre {self.x},{self.y} et de rayons {self.__rx}x{self.__ry}"
def get_dim(self):
return self.__rx, self.__ry
def set_dim(self, rx, ry):
self.__rx = rx
self.__ry = ry
def contient_point(self, x, y):
return ((x - self.x) / self.__rx) ** 2 + ((y - self.y) / self.__ry) ** 2 <= 1
def redimension_par_points(self, x0, y0, x1, y1):
self.x = (x0 + x1) // 2
self.y = (y0 + y1) // 2
self.__rx = abs(x0 - x1) / 2
self.__ry = abs(y0 - y1) / 2
**Sommaire**
[[_TOC_]]
# BE #4 : Application de dessin vectoriel
L'objectif de ce BE est d'apprendre à manipuler quelques composants du module _Python_ _Tkinter_ permettant de créer des interfaces graphiques. Vous allez créer une application simple de dessin vectoriel, qui permettra de tracer à la souris les formes définies dans le BE #2.
---
## Quelques éléments sur _Tkinter_ (45 min.)
Le module _Tkinter_ (_"Tk interface"_) permet de créer des interfaces graphiques. Il contient de nombreux composants graphiques (ou _widgets_), tels que les boutons (classe __Button__), les cases à cocher (classe __CheckButton__), les étiquettes (classe __Label__), les zones d'entrée de texte (classe __Entry__), les menus (classe __Menu__), ou les zones de dessin (classe __Canvas__).
Durant ce BE, nous vous recommandons de conserver le lien vers une [documentation sur _Tkinter_]( https://python.doctor/page-tkinter-interface-graphique-python-tutoriel) ouverte dans un onglet de votre navigateur. Elle contient des exemples de code qui vous seront utiles pour utiliser chacun des _widgets_.
Voici un premier exemple de code _Tkinter_ :
```python
from tkinter import *
from random import randint
class FenPrincipale(Tk):
def __init__(self):
Tk.__init__(self)
# paramètres de la fenêtre
self.title('Tirage aléatoire')
self.geometry('300x100+400+400')
# constitution de l'arbre de scène
boutonLancer = Button(self, text='Tirage')
boutonLancer.pack(side=LEFT, padx=5, pady=5)
self.__texteResultat = StringVar()
labelResultat = Label(self, textvariable=self.__texteResultat)
labelResultat.pack(side=LEFT, padx=5, pady=5)
boutonQuitter = Button(self, text='Quitter')
boutonQuitter.pack(side=LEFT, padx=5, pady=5)
# association des widgets aux fonctions
boutonLancer.config(command=self.tirage) # appel "callback" (pas de parenthèses !)
boutonQuitter.config(command=self.quit) # idem
# tire un entier au hasard et l'affiche dans self.__texteResultat
def tirage(self):
nb = randint(1, 100)
self.__texteResultat.set('Nombre : ' + str(nb))
if __name__ == '__main__':
app = FenPrincipale()
app.mainloop()
```
*Remarque :* La méthode `pack(...)` est utilisée pour organiser les différents éléments dans la fenêtre.
__Exercice 1 -__ Copiez le code suivant dans un fichier appelé *Exo1.py* et exécutez-le pour observer le résultat.
__Attention, utilisateurs de Mac__ : l'association _Spyder_+_Tkinter_ ne fonctionne pas bien sous Mac ! Lorsque vous quitterez l'interface (par le biais du bouton _Quitter_), la fenêtre va se bloquer (_freeze_). Deux solutions:
- soit vous forcez l'application à s'arrêter à chaque fois (utilisez le menu contextuel sur l'icône de l'application concernée dans la barre d'outils);
- soit vous exécutez votre programme en ligne de commande. Pour cela, ouvrez un `Terminal` dans le répertoire de travail (clic-droit sur le répertoire → Nouveau terminal au dossier). Puis lancez le programme exécutant la commande : `python3 Exo1.py`. Vous devriez pouvoir quitter l'application sans difficulté. N'oubliez pas de sauvegarder votre fichier sous _Spyder_ avant toute exécution de cette manière !
Prenez le temps d'étudier cet exemple, et répondez aux questions suivantes :
* Combien d'éléments contient l'arbre de scène ?
* Que se passe-t-il lorsqu'on clique sur le bouton `Tirage` ?
* Comment peut-on inverser les positions des deux boutons ?
* Comment peut-on augmenter l'espace à gauche et à droite du label ?
* Comment peut-on colorier le texte du label en rouge ?
---
## Squelette de l'application de dessin (60 min.)
On souhaite obtenir l'interface ci-dessous, dans laquelle les utilisateurs sélectionneront le type de forme à dessiner avec les boutons, et créeront une forme en cliquant dans la zone située sous la barre d'outils (_widget_ __Canvas__ de _Tkinter_). On a donné une couleur grise au fond de la fenêtre pour vous aider à déterminer les différents _widgets_ présents.
<center><img src="figures/interface.png" style="width:60%"/></center>
Une pratique courante dans les interfaces graphiques est d'intégrer le code de l'application dans l'arbre de scène, en créant des classes qui s'y intégreront comme des nœuds. Ces classes héritent des classes de _Tkinter_ (pour être autorisées à les remplacer dans l'arbre), et nous leur ajouterons des attributs et méthodes spécifiques à leurs responsabilités dans l'application de dessin. Nous allons ainsi introduire deux classes :
* la classe __ZoneAffichage__, qui hérite de __Canvas__ et gère toutes les opérations de dessin spécifiques à votre application.
* la classe __FenPrincipale__, qui hérite de __Tk__ et gère l'initialisation de l'arbre de scène et des _callbacks_ des _widgets_.
Voici le diagramme UML correspondant :
<center><img src="figures/Fenetre_ZoneAffichage_1.svg" style="width:50%"/></center>
En rouge figure les classes de la librairie _Tkinter_, et en jaune vos propres classes.
__Exercice 2 -__ Dessinez l'arbre de scène correspondant à la capture d'écran. Pour chaque nœud vous indiquerez la classe et, s'il y a lieu, sa classe parente également.
__Exercice 3 -__ Complétez le code ci-dessous avec l'initialisation de votre arbre de scène. Vous utiliserez une instance de __ZoneAffichage__ pour implémenter le canevas. À ce stade, on ne vous demande pas de programmer les actions associées aux boutons, mais uniquement de mettre en place le design de l'interface. Vous trouverez des exemples d'utilisation de chacun des _widgets_ dans la documentation référencée plus haut.
```python
from tkinter import *
class ZoneAffichage(Canvas):
def __init__(self, parent, largeur, hauteur):
Canvas.__init__(self, parent, width=largeur, height=hauteur)
class FenPrincipale(Tk):
def __init__(self):
Tk.__init__(self)
self.configure(bg="grey")
# L'initialisation de l'arbre de scène se fait ici
if __name__ == "__main__":
fen = FenPrincipale()
fen.mainloop()
```
---
## Dessin de formes dans le canevas (75 min.)
Vous trouverez dans le dossier de ce BE le fichier [formes.py](formes.py) développé durant le BE #2. Nous avons agrémenté les classes __Rectangle__ et __Ellipse__ pour qu'elles reçoivent un canevas en argument et se dessinent dessus lors de leur initialisation. La classe __Forme__ est maintenant dotée d'une méthode `effacer()` qui supprimera la forme du canevas.
Copiez ce fichier dans votre répertoire de travail.
Ces classes seront intégrées selon le diagramme UML suivant :
<center><img src="figures/Fenetre_ZoneAffichage_2.svg" style="width:90%"/></center>
__Exercice 4 -__ À l'aide de la méthode `bind` vue en cours, reliez les clics de la souris dans le canevas (événements `<ButtonRelease-1>`) à une nouvelle méthode de __ZoneAffichage__ qui imprime les coordonnées de chaque clic avec `print`.
__Exercice 5 -__ Modifiez cette méthode pour créer un nouveau __Rectangle__ centré sur la souris chaque fois que la méthode est exécutée (à ce stade choisissez des dimensions arbitraires). N'oubliez pas de stocker ce rectangle dans __ZoneAffichage__ !
__Exercice 6 -__ Lorsqu'on clique sur le bouton `Ellipse`, l'outil "Ellipse" est sélectionné et tous les futurs clics dans le canevas doivent créer une nouvelle __Ellipse__ (de dimension fixe quelconque). Lorsqu'on clique ensuite sur le bouton `Rectangle`, les clics suivants créeront un __Rectangle__. L'outil sélectionné par défaut est "Rectangle". Modifiez votre code pour implémenter ce comportement.
---
## Opérations de dessin supplémentaires (60 min.)
Nous allons à présent intégrer deux commandes simples dans l'application de dessin :
* Lorsqu'on clique sur une forme en maintenant la touche CTRL enfoncée, elle doit s'effacer du canevas.
* Lorsqu'on clique sur le bouton _Couleur_, un sélecteur de couleurs apparaît pour choisir la couleur de l'outil de dessin.
__Exercice 7 -__ Implémentez l'effacement des formes avec CTRL-clic (événement `<Control-ButtonRelease-1>`). Vous pourrez faire appel aux méthodes `contient_point(...)` des classes __Rectangle__ et __Ellipse__ pour déterminer si la position de la souris au moment de l'événement est dans le périmètre d'une forme donnée, ainsi qu'à la méthode `effacer(...)` de la classe __Forme__.
__Exercice 8 -__ À l'aide du module _colorchooser_ de _Tkinter_ (```from tkinter import colorchooser```), liez les clics sur le bouton _Couleur_ à l'affichage d'un sélecteur de couleur, et utilisez la couleur renvoyée pour tous les ajouts de formes suivants.
---
## Exercices bonus
Il n'y a pas d'ordre prédéfini pour ces trois exercices supplémentaires, choisissez celui dont la fonctionnalité vous semble la plus intéressante.
__Bonus 1 -__ Dans tout programme de dessin respectable, on doit pouvoir dessiner des formes de tailles arbitraires (pas prédéfinies comme précédemment). À l'aide des types d'événements `<Button-1>`, `<B1-Motion>` et `<ButtonRelease-1>`, faites qu'un mouvement de souris avec le bouton enfoncé dessine une forme en tirant ses coins (lorsqu'il ne déplace pas une forme existante). Vous pourrez utiliser les méthodes `redimension_par_points(...)` des classes __Rectangle__ et __Ellipse__.
__Bonus 2 -__ Il serait aussi pratique de pouvoir déplacer les formes présentes sur le canevas. À l'aide des types d'événements `<Button-1>`, `<B1-Motion>` et `<ButtonRelease-1>`, implémentez la translation des formes lors des actions d'appui-déplacement de la souris. Comment faire pour qu'elles n'interfèrent pas avec la création de nouvelles formes ?
__Bonus 3 -__ Maintenant que votre programme de dessin vectoriel est fonctionnel, on doit pouvoir exporter chaque image produite dans un fichier. On utilise pour cela le format SVG, qui est un fichier texte contenant des instructions de dessin. Il suffit d'écrire `<svg viewBox="0 0 600 400" xmlns="http://www.w3.org/2000/svg">` au début du fichier, `</svg>` à la fin, et d'insérer des balises [`rect`](https://developer.mozilla.org/fr/docs/Web/SVG/Element/rect) et [`ellipse`](https://developer.mozilla.org/fr/docs/Web/SVG/Element/ellipse) entre les deux. Pour obtenir un dessin coloré, vous pouvez insérer à l'intérieur des 2 balises, la chaîne `style="fill: brown"` et remplacer `brown` par la couleur de votre forme. C'est maintenant à vous de jouer !
### Consignes pour le rendu (BE #5 - INF-TC2)
Ce BE est le second devoir à rendre concernant INF-TC2. Le compte-rendu (CR) de votre travail devra être déposé sur `Pedagogie1`, sur l'espace de dépôt spécifique à votre groupe. Et cela dans un **délai d'une (1) semaines après la dernière séance consacrée** (délai de rigueur, aucun travail accepté au delà de cette date). Cette semaine ne tient pas compte d'éventuelles vacances. Si vous avez un doute, le plus simple est de contrôler la date pour votre groupe sur `Pedagogie1`.
**Consignes:**
- Le travail peut être individuel ou en binôme. Si vous travaillez en binôme, **un seul dépôt suffit !**.
- Le dépôt consistera en une unique archive (zip, rar) contenant l'ensemble des fichiers suivants :
- Le fichier _Python_, appelé *Pendu.py*, contenant toutes les classes (**FenPrincipale**, **ZoneAffichage** et **MonBoutonLettre**), et un programme principal permettant de lancer l'application.
- Le fichier *mots.txt* et la classe *formes.py* (même s'ils n'ont pas été modifiés).
- un rapport (format _word_, _pdf_, ou mieux encore _markdown_ !) contenant
- Une en-tête où devront figurer le nom des élèves, leur numéro de groupe, le nom de l'encadrant ainsi que le titre du BE.
- Un diagramme de classes UML complet de votre application (pensez à utiliser [diagrams](https://app.diagrams.net) !), avec les liens entre les classes, les cardinalités, les attributs (privés ou publics), et les méthodes (elles-mêmes publiques ou privées).
- Une présentation du code de la DERNIÈRE PARTIE UNIQUEMENT de votre travail (partie intitulée _Améliorations du jeu_). Vous pouvez utilisez des explications textuelles, des diagrammes, des copies d'écran...
- L'archive devra nécessairement porter le nom suivant : *nom1-BE5.zip* ou *nom1-nom2-BE5.zip* (pour les étourdis, pensez à remplacer *nom1* et *nom2* par vos propres noms :-) )
**Critères d'évaluation du travail**
Voici une liste (non exhaustive) de critères qui permettront à vos encadrants d'évaluer vos requêtes :
- **Qualité du rapport** : apparence visuelle globale, orthographe, structure du rapport claire et cohérente. Présence et complétude du diagramme de classes. Qualité des représentations graphiques.
- **Qualité du code** : est-ce qu'il fonctionne sans erreur, le code est-il suffisamment commenté et aéré ? Tests multiples avec des paramètres inattendus ou erronés. Interception des erreurs par des exceptions.
- **Qualité de l'interface** : aspect visuel de l'interface graphique.
\ No newline at end of file
<mxfile host="Electron" modified="2020-10-07T05:23:43.840Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.7.3 Chrome/85.0.4183.98 Electron/10.1.2 Safari/537.36" etag="rDyIsUkNxe0FlCVNYQt9" version="13.7.3" type="device"><diagram id="uKeeR9P6dBSU_i-VrJ_J" name="Page-1">7Zpbl5owEIB/jY/dQxKuj9W9dNttz7b2nO72LUIEukhsDF766xskgIArispq65PJZHKbfCQziR3UG83vGB57n6lDgg5UnHkHXXcgBEDRxU8sWSQS0wSJwGW+I5VyQd//Q6RQkdLId8ikoMgpDbg/LgptGobE5gUZZozOimpDGhR7HWOXVAR9GwdV6Q/f4Z6cBTRy+Qfiu17aM9CtpGSEU2U5k4mHHTpbEaGbDuoxSnmSGs17JIiNl9olqXf7Smk2MEZCvk2F+08fo6l6P3W+uebjg92fLVz3nWxlwhfphBmNQofEdZQO6lLGPerSEAcPlI6FEAjhL8L5Qi4VjjgVIo+PAllK5j5/ktXj9POK/Hq+UnC9SDMhZ4unVC3OPK+W5JWWubTWhDP6ki2KMGe3apF0ejRiNtlgBijJwswlfIMeSvSIU4BG2vuO0BERIxQKjASY+9MiQ1ii6GZ6+WqJhFywHRZPjnqKg0j21IF6IMbfHYiEGycYtv2QZGKWylPJkApTxV9PQNmyCf13RBMFpCjGcDhcFSV1v7+ktcWokwaKjVa7EYqDXLaRuJnnc9If4+V6zcSmUqQLB74birQt1piwtRgM/SDoZRNCYg7QtjPNlRJHH+iavgmcKWGczDcutSxFSH7m6T4ns7N80zCkyFvZL1TlSGygejbElslJSCJ2WDxuGR6RMyOE6K8QYlgDRTkMIQAUCcmOuLdCRK1H5AuNpqIlksyd+wfeSboR5zQ8K1YcjZiOuo4VEw6QfqjdpIgKglVUgNImK1o9K18jn8dGPCwh9ILIK9uJUc9Iq9uJXrFz7Cb1ZTakwg0R/si+3mXV+pm/eQW13V1O5Urbxels7mJaW7qY6alwOB9TVn2k/vL7k/yosMSPUgIjGamsVWIjG0ZzXIw3c1B6OJyKSZ7TltKOhwL1E/NQzHpGRpQflo4HPIivMM4IjnbOG007MTisS4RzYvsHsk4MkbT/TYy8v4Q07YQ0oN5fNVuFA9TD8fMCRytwqPqpwbHubrUc3oTO+/iFIY9uHDzxlksBNgUtqtR8xHG8HC51oLLxArs2GFixk7bGTqls35hBMYrLVLZ/EgVVYoZqQ2pNQ0cOPgCq+Y72efdoIw59i8cPY0sW94QMlrwIoDWEDBjwSis6JLBlzNRjYmb8m5hZ7WCW3XekmOlNMTMrmKGWMdOOhxlowNipE2a2RFjJ481ubHcmzKoQ1vZ5Wb3c/X/PS7QlZmpLmJUucoHZEDPhg5YxKx+9x8bMuJyXO2OmtYRZ6U0SWE0xAxXMykfvsTEzL5jt/i61bSh6YPcflt+l9nD/ywdwY85ENv/jXqKe//0R3fwF</diagram></mxfile>
\ No newline at end of file
seance5_6h/figures/Arbre_scene_pendu.png

26 KiB

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="592px" height="282px" viewBox="-0.5 -0.5 592 282" content="&lt;mxfile host=&quot;Electron&quot; modified=&quot;2020-10-23T14:24:20.314Z&quot; agent=&quot;5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.7.9 Chrome/85.0.4183.121 Electron/10.1.3 Safari/537.36&quot; etag=&quot;j2wcMG27qSD1AfmOCcUu&quot; version=&quot;13.7.9&quot; type=&quot;device&quot;&gt;&lt;diagram id=&quot;uKeeR9P6dBSU_i-VrJ_J&quot; name=&quot;Page-1&quot;&gt;7Zpbl5owEIB/jY/dQxKuj9W9dNttz7b2nO72LUIEukhsDF766xskgIArispq65PJZHKbfCQziR3UG83vGB57n6lDgg5UnHkHXXcgBEDRxU8sWSQSU7ESgct8Ryrlgr7/h0ihIqWR75BJQZFTGnB/XBTaNAyJzQsyzBidFdWGNCj2OsYuqQj6Ng6q0h++wz05C2jk8g/Ed720Z6DL+Y1wqixnMvGwQ2crInTTQT1GKU9So3mPBLHxUrsk9W5fKc0GxkjIt6lw/+ljNFXvp84313x8sPuzheu+k61M+CKdMKNR6JC4jtJBXcq4R10a4uCB0rEQAiH8RThfyKXCEadC5PFRIEvJ3OdPsnqcfl6RX89XCq4XaSbkbPGUqsWZ59WSvNIyl9aacEZfskUR5uxWLZJOj0bMJhvMACVZmLmEb9BDiR5xCtBIe98ROiJihEKBkQBzf1pkCEsU3UwvXy2RkAu2w+LJUU9xEMmeOlAPxPi7A5Fw4wTDth+STMxSeSoZUmGq+OsJKFs2of+OaKKAFMUYDoeroqTu95e0thh10kCx0Wo3QnGQyzYSN/N8TvpjvFyvmdhUinThwHdDkbbFGhO2FoOhHwS9bEJIzAHadqa5UuLoA13TN4EzJYyT+callqUIyc882+eS7CzfNAwp8lb2C1U5Ehuong2xZXISkogdFo9bhkfkzAgh+iuEGNZAUQ5DCABFQrIj7q0QUesR+UKjqWiJJHPn/oF3km7EOQ3PihVHI6ajrmPFhAOkH2o3KaKCYBUVoLTJilbPytfI57ERD0sIvSDyynZi1DPS6naiV+wcu0l9mQ2pcEOEP7Kvd1m1fuZvXkFtd5dTudJ2cTqbu5jWli5meioczseUVR+pv/z+JD8qLPGjlMBIRiprldjIhtEcF+PNHJQeDqdikue0pbTjoUD9xDwUs56REeWHpeMBD+IrjDOCo53zRtNODA7rEuGc2P6BrBNDJO1/EyPvLyFNOyENqPdXzVbhAPVw/LzA0Qocqn5qcKy7Wy2HN6HzPn5hyKMbB0+85VKATUGLKjUfcRwvh0sdqGy8wK4NBlbspK2xUyrbN2ZQjOIyle2fREGVmKHakFrT0JGDD4BqvqN93j3aiEPf4vHD2JLFPSGDJS8CaA0hAwa80ooOCWwZM/WYmBn/JmZWO5hl9x0pZnpTzMwKZqhlzLTjYQYaMHbqhJktEVbyeLMb250JsyqEtX1eVi93/9/zEm2JmdoSZqWLXGA2xEz4oGXMykfvsTEzLuflzphpLWFWepMEVlPMQAWz8tF7bMzMC2a7v0ttG4oe2P2H5XepPdz/8gHcmDORzf+4l6jnf39EN38B&lt;/diagram&gt;&lt;/mxfile&gt;" style="background-color: rgb(255, 255, 255);"><defs/><g><path d="M 301 41 L 158.06 126.76" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 152.92 129.85 L 157.72 122.3 L 158.06 126.76 L 161.84 129.16 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><rect x="301" y="1" width="70" height="40" fill="#fff2cc" stroke="#d6b656" stroke-width="2" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 21px; margin-left: 302px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><b>racine<br /><font color="#007fff">Tk</font><br /></b></div></div></div></foreignObject><text x="336" y="25" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">racine...</text></switch></g><rect x="81" y="131" width="70" height="40" fill="#ffe6cc" stroke="#d79b00" stroke-width="2" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 151px; margin-left: 82px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><b>conteneur<br /><font color="#007fff">Frame</font><br /></b></div></div></div></foreignObject><text x="116" y="155" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">conteneur...</text></switch></g><rect x="1" y="241" width="100" height="40" fill="#d5e8d4" stroke="#82b366" stroke-width="2" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 261px; margin-left: 2px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><b>Nouvelle partie<br /><font color="#007fff">Button</font><br /></b></div></div></div></foreignObject><text x="51" y="265" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Nouvelle partie...</text></switch></g><rect x="141" y="241" width="70" height="40" fill="#d5e8d4" stroke="#82b366" stroke-width="2" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 261px; margin-left: 142px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><b>Quitter<br /><font color="#007fff">Boutton</font><br /></b></div></div></div></foreignObject><text x="176" y="265" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Quitter...</text></switch></g><path d="M 378.5 171 L 326.23 234.64" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 322.42 239.27 L 324.41 230.55 L 326.23 234.64 L 330.59 235.63 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><rect x="231" y="131" width="70" height="40" fill="#ffe6cc" stroke="#d79b00" stroke-width="2" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 151px; margin-left: 232px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><b>conteneur<br /><font color="#007fff">Canvas</font><br /></b></div></div></div></foreignObject><text x="266" y="155" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">conteneur...</text></switch></g><rect x="521" y="131" width="70" height="40" fill="#d5e8d4" stroke="#82b366" stroke-width="2" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 151px; margin-left: 522px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><b>mot<br /><font color="#007fff">Label</font><br /></b></div></div></div></foreignObject><text x="556" y="155" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">mot...</text></switch></g><rect x="361" y="131" width="70" height="40" fill="#ffe6cc" stroke="#d79b00" stroke-width="2" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 151px; margin-left: 362px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><b>conteneur<br /><font color="#007fff">Frame</font><br /></b></div></div></div></foreignObject><text x="396" y="155" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">conteneur...</text></switch></g><rect x="281" y="241" width="80" height="40" fill="#d5e8d4" stroke="#82b366" stroke-width="2" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 261px; margin-left: 282px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><b>A<br /><font color="#007fff">Button</font><br /></b></div></div></div></foreignObject><text x="321" y="265" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">A...</text></switch></g><rect x="431" y="241" width="80" height="40" fill="#d5e8d4" stroke="#82b366" stroke-width="2" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 261px; margin-left: 432px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><b>Z<br /><font color="#007fff">Button</font><br /></b></div></div></div></foreignObject><text x="471" y="265" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Z...</text></switch></g><path d="M 378 261 L 418 261" fill="none" stroke="#000000" stroke-width="4" stroke-miterlimit="10" stroke-dasharray="4 8" pointer-events="stroke"/><path d="M 318.5 41 L 270.15 123.89" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 267.13 129.07 L 267.7 120.14 L 270.15 123.89 L 274.61 124.17 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><path d="M 353.5 41 L 392.48 123.55" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 395.05 128.98 L 388.01 123.45 L 392.48 123.55 L 395.25 120.04 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><path d="M 371 41 L 513.94 126.76" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 519.08 129.85 L 510.16 129.16 L 513.94 126.76 L 514.28 122.3 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><path d="M 98.5 171 L 55.62 234.18" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 52.26 239.15 L 53.44 230.28 L 55.62 234.18 L 60.06 234.78 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><path d="M 133.5 171 L 171.73 233.96" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 174.84 239.09 L 167.27 234.33 L 171.73 233.96 L 174.11 230.17 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><path d="M 413.5 171 L 465.77 234.64" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 469.58 239.27 L 461.41 235.63 L 465.77 234.64 L 467.59 230.55 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://desk.draw.io/support/solutions/articles/16000042487" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
\ No newline at end of file
<mxfile host="Electron" modified="2020-10-04T06:11:11.694Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.7.3 Chrome/85.0.4183.98 Electron/10.1.2 Safari/537.36" etag="Ix25QLi5LQiu-5NG5TtN" version="13.7.3" type="device"><diagram id="dzboKAHa0rqeOh2In6UU" name="Page-1">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</diagram></mxfile>
\ No newline at end of file
seance5_6h/figures/TableSQLJeuPendu.png

14.2 KiB

seance5_6h/figures/pendu0.png

165 KiB

seance5_6h/figures/pendu1.png

45.8 KiB

class Forme:
def __init__(self, canevas, x, y):
self.__canevas = canevas
self._item = None
self.x = x
self.y = y
def effacer(self):
self.__canevas.delete(self._item)
def deplacement(self, dx, dy):
self.__canevas.move(self._item, dx, dy)
self.x += dx
self.y += dy
class Rectangle(Forme):
def __init__(self, canevas, x, y, l, h, couleur):
Forme.__init__(self, canevas, x, y)
self._item = canevas.create_rectangle(x, y, x+l, y+h, fill=couleur)
self.__l = l
self.__h = h
def __str__(self):
return f"Rectangle d'origine {self.x},{self.y} et de dimensions {self.__l}x{self.__h}"
def get_dim(self):
return self.__l, self.__h
def set_dim(self, l, h):
self.__l = l
self.__h = h
def contient_point(self, x, y):
return self.x <= x <= self.x + self.__l and \
self.y <= y <= self.y + self.__h
def redimension_par_points(self, x0, y0, x1, y1):
self.x = min(x0, x1)
self.y = min(y0, y1)
self.__l = abs(x0 - x1)
self.__h = abs(y0 - y1)
class Ellipse(Forme):
def __init__(self, canevas, x, y, rx, ry, couleur):
Forme.__init__(self, canevas, x, y)
self._item = canevas.create_oval(x-rx, y-ry, x+rx, y+ry, fill=couleur)
self.__rx = rx
self.__ry = ry
def __str__(self):
return f"Ellipse de centre {self.x},{self.y} et de rayons {self.__rx}x{self.__ry}"
def get_dim(self):
return self.__rx, self.__ry
def set_dim(self, rx, ry):
self.__rx = rx
self.__ry = ry
def contient_point(self, x, y):
return ((x - self.x) / self.__rx) ** 2 + ((y - self.y) / self.__ry) ** 2 <= 1
def redimension_par_points(self, x0, y0, x1, y1):
self.x = (x0 + x1) // 2
self.y = (y0 + y1) // 2
self.__rx = abs(x0 - x1) / 2
self.__ry = abs(y0 - y1) / 2
ABIME
ABSENT
ACCIDENT
ACCROCHER
ACROBATE
ADROIT
AEROPORT
AFFAIRE
AFFICHE
AGITER
AIDER
AIGUILLE
ALBUM
ALLER
ALPHABET
AMENER
AMI
AMPOULE
AMUSANT
AMUSER
ANCIEN
ANGLE
ANORAK
APPAREIL
APPEL
APPORTER
APPUYER
APPUYER
APRES
ARC
ARMOIRE
ARRACHER
ARRET
ARRETER
ARRIERE
ARRIVER
ARROSER
ARROSOIR
ASSIETTE
ASSIS
ATTACHER
ATTENDRE
ATTENTION
ATTERRIR
ATTRAPER
AUTANT
AUTOUR
AVANCER
AVANT
AVION
BAGAGE
BAGARRE
BAGARRER
BAGUETTE
BAIGNER
BAILLER
BAISSER
BALANCER
BALANCOIRE
BALLE
BALLON
BANC
BANDE
BARBE
BARBOTER
BARRE
BARREAU
BAS
BATEAU
BATTRE
BEAUCOUP
BIBLIOTHEQUE
BICYCLETTE
BIEN
BILLE
BLANC
BLEU
BLOND
BOIS
BOITE
BOITE
BONDIR
BONNET
BORD
BOTTE
BOUCHER
BOUCHON
BOUDER
BOUGER
BOUSCULER
BOUT
BOUTEILLE
BOUTON
BRAS
BRETELLE
BRICOLAGE
BRUIT
BRUN
BULLES
BUREAU
CABANE
CABINET
CACHER
CAGE
CAGOULE
CAHIER
CAISSE
CALME
CAMARADE
CAMESCOPE
CAMION
CANARD
CARNET
CARRE
CARREAU
CARTABLE
CARTE
CARTON
CARTON
CASIER
CASQUE
CASQUETTE
CASSE
CASSER
CASSEROLE
CASSETTE
CATALOGUE
CEINTURE
CERCEAU
CERF
CHAINE
CHAISE
CHAISE
CHANGER
CHANSON
CHANTER
CHAPEAU
CHARGER
CHATEAU
CHAUD
CHAUSSER
CHAUSSETTE
CHAUSSON
CHAUSSURE
CHEMISE
CHERCHER
CHEVILLE
CHIFFRE
CHOISIR
CHOSE
CHUCHOTER
CHUTE
CIGARETTE
CINQ
CISEAUX
CLAIR
CLASSE
CLEF
CLOU
COEUR
COGNER
COIN
COL
COLERE
COLLANT
COLLE
COLLE
COLLER
COLORIAGE
COLORIER
COMMENCER
COMPARER
COMPTER
CONDUIRE
CONSTRUIRE
CONTE
CONTINUER
CONTRAIRE
CONTRE
COPAIN
COPIER
COQUIN
CORDE
CORPS
COTE
COU
COUCHER
COUDE
COUDRE
COULER
COULEUR
COULOIR
COUP
COUPER
COUR
COURIR
COURONNE
COURSE
COURT
COUVRIR
CRACHER
CRAIE
CRAVATE
CRAYON
CREUSER
CRIER
CROCHET
CROCODILE
CUBE
CUILLERE
CUISSE
CULOTTE
CURIEUX
CUVETTE
DAME
DANGER
DANGEUREUX
DANS
DANSER
DE
DEBORDER
DEBOUT
DEBOUT
DECHIRER
DECOLLER
DECORER
DECOUPAGE
DECOUPER
DEDANS
DEFENDRE
DEGONFLER
DEGUISER
DEHORS
DEMARRER
DEMOLIR
DEPASSER
DERNIER
DERRIERE
DESCENDRE
DESHABILLER
DESOBEIR
DESSIN
DESSINER
DESSUS
DETRUIRE
DEUX
DEUXIEME
DEVANT
DICTIONNAIRE
DIFFERENCE
DIFFERENT
DIFFICILE
DIRE
DIRECTEUR
DIRECTRICE
DISCUTER
DISPARAITRE
DISPUTE
DISTRIBUER
DIX
DOIGT
DOIGTS
DOMINO
DONNER
DORMIR
DOS
DOSSIER
DOUCHE
DOUCHER
DOUX
DROIT
DROITE
DU
DUR
EAU
EAU
ECARTER
ECHANGER
ECHARPE
ECHASSE
ECHASSES
ECHELLE
ECLABOUSSER
ECLAIRER
ECOLE
ECORCHER
ECOUTER
ECRAN
ECRASER
ECRIRE
ECRITURE
ECUREUIL
EFFACER
EFFORT
ELASTIQUE
ELEVE
EMMENER
EMPECHER
EMPORTER
ENCORE
ENERVER
ENFANT
ENFILER
ENFONCER
ENGIN
ENLEVER
ENSEMBLE
ENTENDRE
ENTONNOIR
ENTOURER
ENTRER
ENTRER
ENVELOPPE
ENVOLER
ENVOYER
ENVOYER
EPAIS
EPAULE
EPEE
EQUILIBRE
EQUIPE
ESCABEAU
ESCALADE
ESCALADER
ESCALIER
ESSUYER
ETAGERE
ETIQUETTE
ETROIT
EXPLIQUER
EXPLIQUER
EXTERIEUR
FABRIQUER
FACE
FACILE
FAIRE
FATIGUE
FAUTE
FEE
FENETRE
FERMER
FESSE
FEU
FEUILLE
FEUTRE
FICELLE
FIL
FILE
FILET
FILLE
FILM
FINIR
FLAQUE
FLECHE
FLOTTER
FOI
FOIS
FONCE
FOND
FORME
FORT
FOU
FOUILLER
FRAPPER
FREIN
FROID
FUSEE
FUSIL
GAGNER
GALOPER
GANT
GARAGE
GARCON
GARDER
GARDIEN
GARE
GARER
GAUCHE
GENER
GENOU
GENTIL
GLISSER
GOMME
GONFLER
GOUTER
GOUTTES
GRAND
GRIMPER
GRIS
GRONDER
GROS
GROUPE
GRUE
GYMNASTIQUE
HABILLER
HABIT
HANCHE
HANDICAPE
HAUT
HELICOPTERE
HISTOIRE
HUIT
HUMIDE
HURLER
ICI
IDEE
IMAGE
IMITER
IMMOBILE
INONDER
INSEPARABLE
INSTALLER
INSTRUMENT
INTERESSANT
INTERIEUR
INTRUS
JALOUX
JAMAIS
JAMBE
JAUNE
JEAN
JEU
JEU
JOLI
JONGLER
JOUER
JOUET
JOUEUR
JUPE
LACER
LACET
LAINE
LAISSER
LANCER
LARGE
LAVABO
LAVER
LETTRE
LEVER
LIGNE
LINGE
LIRE
LISSE
LISTE
LIT
LITRE
LIVRE
LOIN
LONG
LUNETTES
MADAME
MAGAZINE
MAGICIEN
MAGIE
MAGNETOSCOPE
MAILLOT
MAIN
MAINS
MAITRE
MAITRESSE
MAL
MALADROIT
MANCHE
MANQUER
MANTEAU
MARCHE
MARCHER
MARIONNETTE
MARTEAU
MATELAS
MATERNELLE
MECHANT
MELANGER
MEME
MENSONGE
MESURER
METAL
METRE
METTRE
MEUBLE
MICRO
MIEUX
MILIEU
MINE
MODELE
MODELER
MOINS
MOITIE
MONTAGNE
MONTER
MONTRER
MONTRER
MORCEAU
MOT
MOTEUR
MOTO
MOUCHOIR
MOUFLE
MOUILLE
MOUILLER
MOULIN
MOUSSE
MOYEN
MUET
MULTICOLORE
MUR
MUR
MUSCLE
MUSIQUE
NAGER
NEUF
NOEUD
NOIR
NOM
NOMBRE
NOUVEAU
NU
NUMERO
OBEIR
OBJET
OBLIGER
ONGLE
ORCHESTRE
ORDINATEUR
ORDRE
OUTIL
OUVRIR
OUVRIR
PAGE
PAIRE
PAIX
PANNE
PANTALON
PAPIER
PARCOURS
PARDON
PAREIL
PARKING
PARLER
PARTAGER
PARTIE
PARTIR
PARTIR
PAS
PASSERELLE
PATE
PATTES
PEDALE
PEDALER
PEINDRE
PEINTURE
PEINTURE
PELLE
PELUCHE
PENCHER
PENTE
PERCER
PERCHER
PERDRE
PERLE
PERSONNE
PETIT
PEU
PEUR
PHOTO
PIED
PIED
PILOTE
PINCEAU
PINCEAU
PINCER
PION
PIROUETTE
PLACARD
PLAFOND
PLAINDRE
PLANCHE
PLASTIQUE
PLATRE
PLEURER
PLEUVOIR
PLI
PLIAGE
PLIER
PLONGEOIR
PLONGER
PLUIE
PLUS
PNEU
POCHE
POIGNET
POING
POINT
POINTU
POISSON
POLI
POMPE
PONT
PONT
PORTE
PORTER
POSER
POSER
POSTER
POT
POUBELLE
POUCE
POURSUIVRE
POUSSER
POUTRE
POUVOIR
PREAU
PREMIER
PRENDRE
PRENOM
PREPARER
PRES
PRESENT
PRESQUE
PRESSER
PRESSER
PRETER
PRINCE
PRISE
PRIVER
PROGRES
PROGRESSER
PROMETTRE
PROPRE
PROTEGER
PUNIR
PUZZLE
PYJAMA
QUAI
QUATRE
QUESTION
QUITTER
RACONTER
RADIATEUR
RADIO
RAMPE
RAMPER
RANG
RANGER
RAQUETTE
RATER
RAYON
RAYURE
RECEVOIR
RECHAUFFER
RECITER
RECOMMENCER
RECREATION
RECULER
REFUSER
REGARDER
REINE
REMETTRE
REMPLACER
REMPLIR
RENVERSER
REPARER
REPETER
REPONDRE
RESPIRER
RESSEMBLER
RESTER
RETARD
RETOURNER
REUSSIR
REVENIR
RIDEAU
RIVIERE
ROBE
ROBINET
ROI
ROND
ROND
ROUE
ROUGE
ROULADE
ROULER
ROUX
RUBAN
SABLE
SAC
SAGE
SAIGNER
SALADIER
SALE
SALIR
SALLE
SALON
SAUT
SAUTER
SCIE
SEAU
SEC
SECHER
SEMELLE
SENS
SENTIR
SEPARER
SEPT
SERIEUX
SERPENT
SERRE
SERRER
SERRURE
SERVIETTE
SERVIR
SEUL
SIEGE
SIESTE
SIFFLER
SIFFLET
SIGNE
SIGNE
SILENCE
SINGE
SIX
SOCIERE
SOL
SOLDAT
SOLIDE
SOMMEIL
SONNER
SONNETTE
SORTIE
SORTIR
SOUFFLER
SOULEVER
SOULIGNER
SOUPLE
SOURD
SOURIRE
SOUS
SOUVENT
SPORT
STYLO
SUIVANT
SUIVRE
SUR
SURVEILLER
TABLE
TABLEAU
TABLIER
TABOURET
TACHE
TAILLE
TAILLER
TALON
TAMBOUR
TAMPON
TAPER
TAPIS
TARD
TAS
TASSE
TELECOMMANDE
TELEPHONE
TELEVISION
TENDRE
TENIR
TERMINER
TETE
TIRER
TIROIR
TISSU
TITRE
TOBOGGAN
TOILETTE
TOMBER
TORDU
TOT
TOUCHER
TOUJOURS
TOUR
TOURNER
TOURNEVIS
TRAIN
TRAINER
TRAIT
TRAMPOLINE
TRANQUILLE
TRANSPARENT
TRANSPIRER
TRANSPORTER
TRAVAIL
TRAVAILLER
TRAVERSER
TREMPER
TRICOT
TRICYCLE
TRIER
TROIS
TROISIEME
TROMPETTE
TROP
TROUER
TROUS
TROUSSE
TROUVER
TROUVER
TUNNEL
TUYAU
UN
UNIFORME
USE
VALISE
VELO
VENIR
VENTRE
VERRE
VERS
VERSER
VERT
VESTE
VETEMENT
VIDER
VIRAGE
VIS
VITE
VITESSE
VITRE
VOITURE
VOIX
VOLANT
VOLER
VOULOIR
VOYAGE
WAGON
XYLOPHONE
ZERO
ZIGZAG
**Sommaire**
[[_TOC_]]
# BE #5 : Le jeu du Pendu
L'objectif de ce BE est de réaliser le `jeu du Pendu`. Pour rappel, ce jeu consiste à essayer de découvrir un mot qui est affiché de manière masquée (chacune de ses lettres est remplacée par le caractère _'*'_). Pour cela, le joueur sélectionne une lettre sur le clavier virtuel. Si elle fait partie du mot, alors le mot à découvrir est ré-affiché en laissant apparaître cette lettre en clair. Si par contre le mot ne contient pas la lettre sélectionnée, alors le compteur de coups ratés augmente d'un et l'élément suivant du pendu est ajouté au dessin. Le joueur gagne s'il a pu découvrir le mot avant que le pendu ne soit complètement affiché (au delà de 10 coups manqués). La figure ci-dessous présente l'interface que nous allons construire ; oui, les couleurs piquent un peu aux yeux, mais ça vous aidera à répondre à la première question !
<center><img src="figures/pendu0.png" style="width:60%"/></center>
Nous allons vous accompagner dans le développement de ce programme. La première partie (90 minutes) porte sur la mise en place de l'interface graphique. La seconde (75 minutes) porte sur la logique du jeu, à partir des commandes associées au bouton _Nouvelle Partie_ et aux Boutons-lettres. La troisième partie met en place le dessin du pendu (75 minutes). La dernière partie propose de développer des fonctionnalités supplémentaires à notre application durant l'autonomie (avec une question _Bonus_ pour les plus téméraires !).
Ce BE fera l'objet d'un compte-rendu (CR), seul ou en binôme. L'énoncé correspond à 4h de TD encadrées et 2h d'autonomie. Avant de commencer, veuillez prendre connaissance des consignes concernant le rendu du travail (à respecter scrupuleusement) qui se trouvent dans le fichier [consignes_BE#5.md](./consignes_BE#5.md), dans le même répertoire que cet énoncé.
---
## Partie 1 - Mise en place de l'interface statique (90 min.)
__Exercice 1 -__ Dessinez l'arbre de scène correspondant à la capture d'écran ci-dessus.
__Exercice 2 -__ En vous inspirant de l'organisation des classes du BE #4, programmez l'interface statique (_i.e._ sans programmer les commandes associées aux boutons) en distinguant la classe __FenPrincipale__ et la classe __ZoneAffichage__. À ce stade, à la place des 26 boutons du clavier (correspondant aux 26 lettres en majuscule), placez un simple bouton _"A"_ car le dessin du clavier est traité dans l'exercice suivant.
Testez votre interface et faites les ajustements nécessaires pour obtenir une apparence proche de celle donnée en exemple (mais sans le clavier, et avec les couleurs qui vous conviennent !). Le programme principal se réduira à ces quelques lignes :
```python
if __name__ == '__main__':
fen = FenPrincipale()
fen.mainloop()
```
_Remarque_ : Vous pouvez à ce stade ajouter la commande _self.destroy_ sur le bouton _Quitter_.
__Exercice 3 -__ Nous allons maintenant dessiner le clavier tel qu'il apparaîtra dans la version finale.
1. __Liste des boutons__ Les 26 boutons seront créés et stockés dans une liste de boutons. Pour transformer les nombres de 0 à 25 en lettres _A_, ..., _Z_, vous pourrez utiliser l'instruction suivante ```t = chr(ord('A')+i)``` qui transforme l'entier _i=0_ en une chaîne d'un seul caractère _t="A"_, l'entier _i=1_ en une chaîne d'un seul caractère _t="B"_, ...
1. __Placement des boutons__ La disposition des boutons en grille sera réalisée grâce à la commande _grid_, selon l'exemple suivant : ```unBouton.grid(row=1, column=2)``` positionne _unBouton_ sur la première ligne, seconde colonne de la grille (dont la taille s'adapte automatiquement).
Pensez à exécuter votre programme pour vérifier le placement du clavier virtuel.
---
## Partie 2 - Logique de jeu, commandes (75 min.)
Cette partie est destinée à implémenter la logique de jeu, à travers les commandes de l'interface :
- _Bouton "Quitter"_ (vous l'avez peut être déjà fait, _cf_ remarque ci-dessus).
- _Bouton "Nouvelle partie"_.
- _Boutons-lettres "A", ..., "Z"_.
On fait ici abstraction de la représentation graphique du pendu qui sera traitée dans la partie suivante. Allons-y pas-à-pas...
### Bouton "Nouvelle Partie" (30 min.)
Une partie ne pourra commencer que si le joueur appuie sur le bouton "Nouvelle partie".
__Exercice 4 -__ L'appuie sur ce bouton doit provoquer une ré-initialisation de toute l'interface :
- Tirer un nouveau mot au hasard dans le fichier [mots.txt](./mots.txt) (à votre disposition à côté de cet énoncé) et réinitialiser le mot à découvrir;
- Dégriser les boutons-lettres (par la commande suivante ```unBouton.config(state=NORMAL)```);
- Effacer le dessin du pendu (question traitée dans la partie suivante de cet énoncé).
_Quelques conseils pour l'implémentation_
- Au lancement de l'application, pensez à griser toutes les lettres du clavier (l'utilisateur comprend alors qu'il doit appuyer sur le bouton "Nouvelle partie").
- Utilisez la méthode suivante pour charger les mots du fichier _mots.txt_ dans une liste privée appelée _self.\_\_mots_. Cette liste sera chargée une fois pour toute au lancement de l'application, et utilisée à chaque nouvelle partie.
```python
def chargeMots(self):
f = open('mots.txt', 'r')
s = f.read()
self.__mots = s.split('\n')
f.close()
```
- Pour tirer un nouveau mot au hasard, utilisez la fonction _randint(...)_ (```from random import randint```).
Pensez à vérifier que votre application est bien fonctionnelle à ce stade.
### Boutons-lettres "A", ..., "Z" (45 min.)
Le fait d'appuyer sur une lettre du clavier virtuel doit provoquer un certain nombre d'actions :
- griser le bouton-lettre qui vient d'être cliqué (```state=DISABLED```);
- faire apparaître autant de fois que nécessaire la lettre cliquée dans le mot à découvrir;
- vérifier si la partie est perdue, gagnée, ou si elle se poursuit;
- éventuellement, compléter le dessin du pendu si la lettre n'est pas présente dans le mot (action traitée dans la partie suivante de cet énoncé).
Chaque bouton doit pouvoir être identifié par la fonction de _callback_ appelée ici _cliquer_. Or il n'est pas possible de passer le numéro du bouton-lettre au _callback_ (aucun argument n'est permis). Nous allons procéder en créant notre propre classe de boutons, héritant de la classe __Button__.
__Exercice 5 -__ Suivez les étapes proposées
1. Créer la classe __MonBoutonLettre__, qui hérite de la classe __Button__, et qui sauvegarde, en tant qu'attribut privé, la lettre correspondant au bouton (ou le numéro du bouton). Modifier en conséquence le constructeur de la classe __FenPrincipale__ pour que le clavier virtuel soit composé de 26 instances de la classe __MonBoutonLettre__.
1. Créer la fonction de callback _cliquer(self)_ dans la classe __MonBoutonLettre__, qui fera notamment appel à une méthode _traitement(...)_ de la classe __FenPrincipale__.
1. Programmer cette méthode _traitement(...)_ dont l'objectif est de mettre à jour l'affichage du mot.
- Si la partie est gagnée, bloquez l'utilisation du clavier, et affichez un texte qui indique au joueur que c'est gagné !
- La partie est perdue quand le nombre de coups dépasse 10 (c'est le nombre d'éléments nécessaires pour dessiner entièrement le pendu). Bloquez alors l'utilisation du clavier, et affichez un texte qui indique au joueur que c'est perdu !
À ce stade, l'application doit être entièrement fonctionnelle, seul le dessin du pendu est manquant, ce que nous allons compléter dès à présent...
---
## Partie 3 - Le dessin du pendu (75 min.)
Cette partie est consacrée au dessin progressif du pendu, au fur et à mesure des échecs du joueur. Ce dessin s'appuie sur les connaissances acquises lors du BE #4 et les classes du fichier [formes.py](./formes.py), disponible à côté de cet énoncé pour ceux qui le souhaitent. L'idée est de créer le pendu comme une liste de rectangles et d'ellipses (10 pièces doivent suffire).
Le parti pris ici est de créer et de dessiner les 10 pièces du pendu dans le constructeur de la classe __ZoneAffichage__, mais en leur affectant la propriété `state="hidden"`, de telle sorte qu'elles ne soient pas visibles. Ce n'est qu'au fur et à mesure de l'avancement d'une partie que les pièces apparaissent sur le canevas, en passant du statut `"hidden"` au statut `"normal"`. La réinitialisation liée à une nouvelle partie consistera alors à cacher l'ensemble des pièces.
*Remarque* : Notez qu'il aurait aussi été possible d'adopter un autre point de vue qui consisterait à créer et dessiner chaque pièce lors de chaque partie.
__Préliminaires sur le fichier [formes.py](./formes.py)__
- Modifier le fichier [formes.py](./formes.py) de telle manière que les rectangles et les ellipses soient cachés lors de leur création.
- Il est nécessaire de prévoir une méthode _setState(s)_ qui permette de changer ce statut. La méthode étant identique pour les rectangles et pour les ellipses, il convient de la factoriser dans la classe __Forme__ :
```python
def setState(self, s):
self.__canevas.itemconfig(self._item, state=s)
```
__Exercice 6 -__ Mettez en place la stratégie décrite ci-dessus pour terminer l'application.
Pour gagner un peu de temps, voici un exemple de jeu de pièces (avec leur position et leurs dimensions) qui permettent de dessiner le pendu de la première figure.
```python
# Base, Poteau, Traverse, Corde
Rectangle(self, 50, 270, 200, 26, "brown")
Rectangle(self, 87, 83, 26, 200, "brown")
Rectangle(self, 87, 70, 150, 26, "brown")
Rectangle(self, 183, 67, 10, 40, "brown")
# Tete, Tronc
Rectangle(self, 188, 120, 20, 20, "black")
Rectangle(self, 175, 143, 26, 60, "black")
# Bras gauche et droit
Rectangle(self, 133, 150, 40, 10, "black")
Rectangle(self, 203, 150, 40, 10, "black")
# Jambes gauche et droite
Rectangle(self, 175, 205, 10, 40, "black")
Rectangle(self, 191, 205, 10, 40, "black")
```
Rien ne vous empêche de customiser votre pendu !
---
## Partie 4 - Améliorations du jeu (autonomie)
Voici quelques améliorations pour le jeu, à rendre compte dans votre CR. Seule la dernière amélioration est considérée comme un bonus.
__Exercice 7 - Apparence__ Développez le code qui permet au joueur de choisir les couleurs principales de l'application (par un menus, par des boutons...).
__Exercice 8 - Triche !__ Implémentez une technique "_Undo_" qui permet de revenir de un ou plusieurs coups en arrière, au cours d'une partie.
__Bonus - Score joueur__ Implémentez un système de sauvegarde des échecs et des succès d'un joueur (identifié par un pseudo demandé au joueur en début de partie). Techniquement, on pourra créer une base de données _SQL_ (_cf_ BE #3), appelée _pendu.db_, qui stockera une table avec les joueurs et une table avec les parties jouées par ces joueurs, selon le schéma suivant :
<center><img src="figures/TableSQLJeuPendu.png" style="width:30%"/></center>
Le score pour chaque mot pourra être défini comme le taux de caractères trouvés (ainsi un score de 1.0 désigne un succès).
Dans un premier temps, pour vérifier que votre programme fonctionne, vous pouvez consulter la base _pendu.db_ à l'aide de ```DB Browser for SQLite```. Si vous le souhaitez, vous pouvez alors intégrer à votre application un affichage de l'historique des parties du joueur et/ou de ses performances.
tuto-git-gitlab/figures/AjoutEncadrant.png

106 KiB