affichage label

Bonjour,
voici la structure de mon programme:

import modules
fen=Tk()
...
label1=Label(fen,text,...)
...
# lecture des @ sites web dans un fichier csv
# test si @ site valide
# affichage des erreurs (Labels)
fen.mainloop()

Je dois attendre la fin du programme pour afficher le label1 alors qu’il est au début du programme. Merci de m’expliquer pourquoi cela se passe ainsi.

Salut,

Je pense comprendre le souci que tu rencontres et vais donc l’illustrer par un code fonctionnel un peu plus complet.

import tkinter
import time

# Initialisation des objets
win = tkinter.Tk()
label1 = tkinter.Label(win, text="before loading")
label1.pack()

# Traitements lourds, représentés par des attentes
for i in range(5):
    time.sleep(1)

# Fin du traitement, ajout d'un nouveau label
label2 = tkinter.Label(win, text="after loading")
label2.pack()

# Boucle de jeu
win.mainloop()

Et là… ça ne se passe pas comme prévu.
Alors que j’affiche mon 1er label à la ligne 7, celui-ci n’apparaît à l’écran (avec la fenêtre) qu’à la fin du programme, donc après les traitements.

Ce n’est pas beaucoup mieux si je déplace win.mainloop() plus haut : mon 1er label apparaît bien mais le 2nd n’apparaît jamais.


Il s’agit d’un problème de programmation concurrente !
En fait, le souci est qu’on a un seul fil d’exécution, qui grossièrement ne peut faire qu’une chose à la fois.

S’il est en train d’exécuter des traitements il n’affiche pas la fenêtre, et inversement.

Ce qu’il nous faudrait c’est un moyen de faire plusieurs choses en même temps, et une solution à ça et l’utilisation de threads (fils d’exécution).

Un thread c’est un nouveau fil que tu lances et qui va faire un autre traitement en même temps que le tien (c’est le processeur qui gère ça) et faire en sorte de ne pas se bloquer.

Dans le cas que je présente ça donnerait quelque chose comme :

import tkinter
import time
import threading

# Initialisation des objets
win = tkinter.Tk()
label1 = tkinter.Label(win, text="before loading")
label1.pack()

def handler():
    # Traitements lourds, représentés par des attentes
    for i in range(5):
        time.sleep(1)

    # Fin du traitement, ajout d'un nouveau label
    label2 = tkinter.Label(win, text="after loading")
    label2.pack()

thread = threading.Thread(target=handler)
thread.start()

# Boucle de jeu
win.mainloop()
thread.join()

On voit que j’initialise un thread avec une fonction cible (target), que je le démarre (thread.start()) puis que je l’attends à la fin du programme (thread.join()) pour quitter proprement.

Bien sûr cet exemple n’est valable que pour de vrais traitements qui seraient réalisés dans handler : s’il ne s’agissait que d’attendre 5 secondes, on exploiterait le mécanisme de timers (win.after) de tkinter.

1 « J'aime »

un grand merci pour ces expliquations très claires que je viens de mettre en pratique et qui fonctionnent parfaitement.