blog: tkinter
This commit is contained in:
parent
d7f401d3f7
commit
467ce418c0
1 changed files with 305 additions and 0 deletions
305
content/blog/tkinter.fr.md
Normal file
305
content/blog/tkinter.fr.md
Normal file
|
@ -0,0 +1,305 @@
|
|||
+++
|
||||
title = "Tutoriel Tkinter Python"
|
||||
date = 2024-10-30
|
||||
description = "Initiation aux interfaces graphiques"
|
||||
insert_anchor_links = "left"
|
||||
[taxonomies]
|
||||
tags = ["programmation", "Python"]
|
||||
+++
|
||||
|
||||
**Prérequis** :
|
||||
Il faut être un peu à l'aise avec le Python, au moins les variables, fonctions, manipulation des chaînes de caractères.
|
||||
Si ce n'est pas le cas, [France-IOI](https://www.france-ioi.org/algo/chapters.php) propose une introduction ludique au Python.
|
||||
|
||||
Tkinter est une bibliothèque d'interface graphique, qui permet de créer des fenêtres sous Linux, Windows et Mac.
|
||||
C'est une des plus simples à utiliser en Python.
|
||||
Seulement elle est un peu vieille et trop peu intuitive, d'où ce tutoriel qui peut servir de mini-référence.
|
||||
|
||||
Pour aller plus loin : [TkDocs Tutorial](https://tkdocs.com/tutorial/index.html) (en anglais)
|
||||
|
||||
[Ce tutoriel est disponible en PDF.](/o/tuto/tkinter.pdf)
|
||||
Le code source et les commandes utilisées pour générer le PDF sont disponibles [dans ce dépôt Git](https://git.txmn.tk/tuxmain/jsb-editor).
|
||||
|
||||
## Code de base
|
||||
|
||||
Créer une fenêtre vide :
|
||||
|
||||
```python
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
|
||||
root = tk.Tk()
|
||||
|
||||
root.mainloop()
|
||||
```
|
||||
|
||||
Ajouter des boutons dans la fenêtre :
|
||||
|
||||
```python
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
|
||||
root = tk.Tk()
|
||||
|
||||
bt1 = ttk.Button(root, text="Bonjour")
|
||||
bt1.grid(column=0, row=0)
|
||||
|
||||
bt2 = ttk.Button(root, text="Au revoir")
|
||||
bt2.grid(column=1, row=0)
|
||||
|
||||
root.mainloop()
|
||||
```
|
||||
|
||||
### Positionnement
|
||||
|
||||
On peut changer le nombre de colonnes ou de lignes occupées par un widget en ajoutant les paramètres `columnspan` ou `rowspan` en plus de `column` et `row`.
|
||||
|
||||
Pour coller un widget au bord de la grille, on peut ajouter `sticky` :
|
||||
|
||||
```python
|
||||
bt2.grid(column=1, row=0, sticky=(tk.W, tk.N))
|
||||
```
|
||||
|
||||
`sticky` prend une liste de 0 à 4 éléments parmi :
|
||||
|
||||
* `tk.E` : _East_ = droite
|
||||
* `tk.N` : _North_ = haut
|
||||
* `tk.S` : _South_ = bas
|
||||
* `tk.W` : _West_ = gauche
|
||||
|
||||
### Redimensionner la fenêtre
|
||||
|
||||
Il faut indiquer quelles lignes et colonnes doivent changer de taille quand la fenêtre change de taille.
|
||||
|
||||
Dans cet exemple, ce sont la ligne 1 et la colonne 0.
|
||||
|
||||
```python
|
||||
root.rowconfigure(1, weight=1)
|
||||
root.columnconfigure(0, weight=1)
|
||||
```
|
||||
|
||||
On peut appeler plusieurs fois ces fonctions pour choisir plusieurs lignes et colonnes, et changer les `weight` pour modifier les proportions.
|
||||
|
||||
## Widgets
|
||||
|
||||
Tous les widgets doivent être positionnés avec `grid`, de la même manière que ci-dessus.
|
||||
Sans ça, ils ne seront pas affichés !
|
||||
|
||||
### Label
|
||||
|
||||
Juste du texte.
|
||||
|
||||
```python
|
||||
label = ttk.Label(root, text="Je suis un texte. Wow.")
|
||||
```
|
||||
|
||||
On peut aussi modifier le texte plus tard :
|
||||
|
||||
```python
|
||||
label_text = tk.StringVar()
|
||||
label["textvariable"] = label_text
|
||||
label_text.set("Le nouveau texte. Tout ça pour ça !")
|
||||
```
|
||||
|
||||
### Bouton
|
||||
|
||||
Un bouton qu'on peut cliquer.
|
||||
|
||||
```python
|
||||
def onclick():
|
||||
print("On a cliqué")
|
||||
|
||||
bt = ttk.Button(root, text="Cliquez-moi", command=onclick)
|
||||
```
|
||||
|
||||
### Image
|
||||
|
||||
Un bouton ou un label peut afficher une image :
|
||||
|
||||
```python
|
||||
img = tk.PhotoImage(file='image.png')
|
||||
label["image"] = img
|
||||
```
|
||||
|
||||
### Entrée de texte
|
||||
|
||||
Boîte dans laquelle on peut écrire une ligne de texte.
|
||||
|
||||
```python
|
||||
text = tk.StringVar()
|
||||
entry = ttk.Entry(root, textvariable=text)
|
||||
```
|
||||
|
||||
Plus tard, on peut récupérer le texte :
|
||||
|
||||
```python
|
||||
print("L'utilisateur a écrit :", text.get())
|
||||
```
|
||||
|
||||
### Entrée de texte multiligne
|
||||
|
||||
Zone dans laquelle on peut écrire du texte en plusieurs lignes.
|
||||
|
||||
```python
|
||||
text = tk.Text(root)
|
||||
```
|
||||
|
||||
Il y a plusieurs méthodes pour interagir avec le texte :
|
||||
|
||||
```python
|
||||
print(text.get("1.0", "end")) # obtenir tout le texte
|
||||
print(text.get("2.0", "8.0")) # le texte de la ligne 2 à la ligne 8
|
||||
text.replace("1.0", "end", "le nouveau texte") # remplacer du texte
|
||||
text.insert("1.0", "le nouveau texte") # insérer du texte
|
||||
text.insert("1.0 +42 chars", "le nouveau texte")
|
||||
text.insert("end -3 lines", "le nouveau texte")
|
||||
```
|
||||
|
||||
Pour mettre en forme certaines parties du texte, on peut utiliser des tags :
|
||||
|
||||
```python
|
||||
text.tag_configure("fond_rouge", background="#ffaaaa")
|
||||
text.tag_configure("insistance", foreground="#008800", underline=True)
|
||||
|
||||
text.insert("1.0", "ce texte sera sur fond rouge", "fond_rouge")
|
||||
text.tag_add("insistance", "1.3", "1.8")
|
||||
```
|
||||
|
||||
[Liste de tous les styles possibles.](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M43)
|
||||
|
||||
### Barre de défilement
|
||||
|
||||
Certains widgets (`Text`) peuvent défiler avec la molette, mais pour afficher la barre de défilement il faut un widget supplémentaire.
|
||||
|
||||
```python
|
||||
scroll = ttk.Scrollbar(root, orient=tk.VERTICAL, command=mon_widget_qui_défile.yview)
|
||||
scroll.grid(column=1, row=0, sticky=(tk.N, tk.S, tk.E, tk.W))
|
||||
mon_widget_qui_défile.configure(yscrollcommand=scroll.set)
|
||||
```
|
||||
|
||||
### Cadre
|
||||
|
||||
Un cadre qui peut avoir une bordure et contenir d'autres widgets.
|
||||
|
||||
```python
|
||||
frame = ttk.Frame(root, borderwidth=5, relief="ridge", width=200, height=100)
|
||||
```
|
||||
|
||||
Les options ne sont pas obligatoires.
|
||||
|
||||
Le cadre contient ses propres lignes et colonnes.
|
||||
Pour placer des widgets dedans, il suffit de remplacer `root` par `frame` en les créant.
|
||||
|
||||
### Barre de menus
|
||||
|
||||
La barre de menus en haut de la fenêtre.
|
||||
|
||||
```python
|
||||
root.option_add('*tearOff', False)
|
||||
menubar = tk.Menu(root)
|
||||
root['menu'] = menubar
|
||||
|
||||
menu_file = tk.Menu(menubar)
|
||||
menu_edit = tk.Menu(menubar)
|
||||
|
||||
menubar.add_cascade(menu=menu_file, label='Fichier')
|
||||
menubar.add_cascade(menu=menu_edit, label='Édition')
|
||||
|
||||
menu_file.add_command(label='Ouvrir', command=on_open)
|
||||
```
|
||||
|
||||
### Canevas
|
||||
|
||||
Le canevas est une zone de dessin.
|
||||
|
||||
```python
|
||||
canvas = tk.Canvas(root, background='white')
|
||||
```
|
||||
|
||||
On peut y dessiner des formes :
|
||||
|
||||
```python
|
||||
canvas.create_line(x1, y1, x2, y2)
|
||||
canvas.create_line(x1, y1, x2, y2, fill="red", width=3, dash=6)
|
||||
canvas.create_rectangle(x1, y1, x2, y2, fill="red", outline="blue")
|
||||
canvas.create_oval(x1, y1, x2, y2, fill="red", outline="blue")
|
||||
```
|
||||
|
||||
## Événements
|
||||
|
||||
Quand il se passe quelque chose sur un widget, un événement est généré.
|
||||
On peut écouter les événements de certains types, c'est-à-dire lancer une fonction quand l'action se produit.
|
||||
|
||||
Par exemple, on affiche des informations quand une touche du clavier est relâchée dans la zone de texte :
|
||||
|
||||
```python
|
||||
text = tk.Text(root)
|
||||
|
||||
def onrelease(event):
|
||||
print("On a frappé le clavier !")
|
||||
print(event)
|
||||
|
||||
text.bind("<KeyRelease>", onrelease)
|
||||
```
|
||||
|
||||
On peut aussi utiliser les infos contenues dans l'événement, par exemple `event.keycode`.
|
||||
|
||||
### Liste des événements
|
||||
|
||||
* Souris
|
||||
* `ButtonPress`: clic enfoncé d'un bouton de la souris
|
||||
* `Button-1`: comme `ButtonPress` mais seulement pour le clic gauche
|
||||
* `Button-2`: comme `ButtonPress` mais seulement pour le clic molette
|
||||
* `Button-3`: comme `ButtonPress` mais seulement pour le clic droit
|
||||
* `ButtonRelease`: clic relâché d'un bouton de la souris
|
||||
* `Double-1`: double-clic gauche
|
||||
* `Double-3`: double-clic droit
|
||||
* `Enter`: le pointeur de la souris entre
|
||||
* `Leave`: le pointeur de la souris sort
|
||||
* `Motion`: le pointeur de la souris bouge dedans
|
||||
* `B1-Motion`: comme `Motion` mais avec le clic gauche enfoncé
|
||||
* `B2-Motion`: comme `Motion` mais avec le clic molette enfoncé
|
||||
* `B3-Motion`: comme `Motion` mais avec le clic droit enfoncé
|
||||
* Clavier
|
||||
* `KeyPress`: appui d'une touche du clavier
|
||||
* `KeyRelease`: relâche d'une touche du clavier
|
||||
* Widget
|
||||
* `Configure`: le widget est créé
|
||||
* `Expose`: le widget est affiché ou réaffiché
|
||||
* `FocusIn`: le widget reçoit le focus
|
||||
* `FocusOut`: le widget pert le focus
|
||||
|
||||
## Dialogues
|
||||
|
||||
On peut ouvrir des fenêtres pour dire ou demander des choses.
|
||||
|
||||
### Fichiers
|
||||
|
||||
Demander où enregistrer un fichier, quel fichier ouvrir, choisir un dossier.
|
||||
|
||||
```python
|
||||
from tkinter import filedialog
|
||||
|
||||
filetypes = [
|
||||
("Texte", "*.txt"),
|
||||
("Image PNG", "*.png"),
|
||||
("Autre", "*.*")
|
||||
]
|
||||
chemin = tk.filedialog.asksaveasfilename(filetypes=filetypes)
|
||||
print(chemin)
|
||||
```
|
||||
|
||||
On peut remplacer `asksaveasfilename` par `askopenfilename` ou `askdirectory`.
|
||||
|
||||
### Couleur
|
||||
|
||||
Demander de choisir une couleur.
|
||||
|
||||
```python
|
||||
from tkinter import colorchooser
|
||||
|
||||
color = colorchooser.askcolor(initialcolor='black')
|
||||
print(color)
|
||||
```
|
||||
|
||||
On peut aussi indiquer la couleur initiale avec sa notation hexadécimale `"#000000"`.
|
Loading…
Reference in a new issue