J'ai écrit une maquette d'utilisation d'une Listebox avec un Scrollbarr que j'utiliserai dans un programme de gestion de photos de fleurs.
Je choisirai la photo à visualiser via la selection effectuée dans la listebox.
Je veux aller au début de la listbox et à la fin par les touches <Shift-Up> et <Shift-Down> que lorsque le curseur de la souris est sur la listbox.
La maquette fonctionne bien, sauf lorsque le curseur est hors de la listbox, les <Shift-Up> et <Shift-Down> étant toujours opérantes.
Voici ma maquette
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import tkinter as tk
class UtilisationListbox(tk.Tk):
    '''
    Exemle d'utilisation d'une Listbox liée à un scrollbar vertical
    C'est une application de l'utilisation des méthodes after et after_cancel
    pour la sélection à la volée d'une ligne de la Listbox avec lancement d'une
    méthode paramérée avec la sélection
    '''
    def __init__(self,parent=None):
        tk.Tk.__init__(self,parent)
 
        self.sel=() #sert pour initier le if dans la méthode ParcourirListbox
 
        self.F1=tk.Frame(self)             #Création du Frame contenant la Listbox et le Scrollbar
        self.s=tk.Scrollbar(self.F1)       #Création du Scrollbar
        self.L=tk.Listbox(self.F1)         #Création de la Listbox
        for i in range(30):                #Remplissage de la Listbox
            self.L.insert(tk.END,str(i))
 
        self.L.selection_set(0) #selectionne la ligne 1 de la Listbox
        self.L.activate(0) #Active la ligne 1 de la Listebox
        self.L.configure(state='disabled') #Désactive la sélection relativement à la souris
 
        #Lient la Listebox à différents évènements
        self.L.bind('<Enter>',lambda evt: self.ParcourirListbox())       #Le curseur entre sur la Listbox
        self.L.bind('<Leave>',lambda evt: self.NePlusParcourirListbox()) #Le curseur dort de la Listebox
        self.L.bind('<Shift-Up>',self.AllerEnHaut)                       #Sélectionne la première ligne de la Listbox
        self.L.bind('<Shift-Down>',self.AllerEnBas)                      #Sélectionne la dernière ligne de la Listbox
 
        #Positionnement de et dans la Frame contenant la Listbox et le scrollbarr
        self.F1.pack(side=tk.TOP)      
        self.s.pack(side=tk.RIGHT,fill=tk.Y)
        self.L.pack(side=tk.LEFT,fill=tk.Y)
 
        #Liaison entre la Listbox et le Scrollbarr
        self.L['yscrollcommand']=self.s.set
        self.s['command']=self.L.yview  
 
        #Création de la Frame et du Label contenant le résultat de la sélection
        self.F2=tk.Frame()
        self.lab=tk.Label(self.F2)
 
        #Positionnement de et dans la Frame contenant le label
        self.F2.pack(side=tk.TOP)
        self.lab.pack()
 
    def ParcourirListbox(self):
        #Le curseur rentre dans la Listbox
        self.L.configure(state='normal') #Active la sélection de la Listbox relativement à la souris
        #Initie la commande after qui permet d'attendre 200ms avant de selectionner la ligne en cours de la Listbox
        self.p=self.lab.after(200,self.ParcourirListbox)
        if self.L.curselection()!=self.sel: #Vérifie si la sélection à changer
            self.sel=self.L.curselection()
            self.lab.config(text=str(self.sel[0]))
            self.LancerProgramme(self.sel) #Lance un programme utilisant la nouvelle sélection
 
    def NePlusParcourirListbox(self):
        #Le curseur sort de la Listbox
        self.L.configure(state='disabled') #Désactivation de la Listbox relativement à la souris
        self.lab.after_cancel(self.p) #Suppression de l'instance after en cours
        self.L.unbind_all('<Shift-Up>,<Shift-Down>') #Suppressin des liaisons
 
    def LancerProgramme(sel,x):
        #Lance le programme lors d'une nouvelle sélection
        print("Programme lancé avec",x)
 
    def AllerEnHaut(self,evt):
        '''
        Sélectionne la première ligne de la sélection lors de l'appuie
        conjoint des touches "Shift" et "Flèche haut"
        '''
        if self.focus_get()==self.L:
            print(self.focus_get(),evt.widget)
            self.L.selection_clear(0,tk.END) #Désélection de la ligne sélectionnée
            self.L.activate(0) #Activation de la première ligne
            self.L.selection_set(0) #Sélection de la première ligne
            self.L.see(0) #Visualisation de la première ligne
 
    def AllerEnBas(self,evt):
        '''
        Sélectionne la dernière ligne de la sélection lors de l'appuie
        conjoint des touches "Shift" et "Flèche bas"
        '''        
        self.L.selection_clear(0,tk.END) #Désélection de la ligne sélectionnée
        self.L.activate(tk.END) #Activation de la dernière ligne
        self.L.selection_set(tk.END) #Sélection de la dernière ligne
        self.L.see(tk.END) #Visualisation de la dernière ligne    
 
if __name__=="__main__":
    test=UtilisationListbox(None)
    test.title("Test after dans une classe")
    test.mainloop()
J'ai essayé la méthode self.L.unbind_all('<Shift-Up>,<Shift-Down>') (ligne 61) mais ça ne fonctionne pas
J'ai également essayé if self.focus_get()==self.L: dans méthode AllerEnHaut(self,evt) (ligne 72), mais la listbox L a toujours le focus!

Merci de vos idées pour me dépanner