Comment supprimer le focus sur une listbox quand le curseur de la souris n'y est plus
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:
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