J'ai ce cadre défilable (cadre à l'intérieur de la toile en fait).
import Tkinter as tk
class Scrollbarframe():
def __init__(self, parent,xsize,ysize,xcod,ycod):
def ScrollAll(event):
canvas1.configure(scrollregion=canvas1.bbox("all"),width=xsize,height=ysize,bg='white')
self.parent=parent
self.frame1=tk.Frame(parent,bg='white')
self.frame1.place(x=xcod,y=ycod)
canvas1=tk.Canvas(self.frame1)
self.frame2=tk.Frame(canvas1,bg='white',relief='groove',bd=1,width=1230,height=430)
scrollbar1=tk.Scrollbar(self.frame1,orient="vertical",command=canvas1.yview)
canvas1.configure(yscrollcommand=scrollbar1.set)
scrollbar1.pack(side="right",fill="y")
canvas1.pack(side="left")
canvas1.create_window((0,0),window=self.frame2,anchor='nw')
self.frame2.bind("<Configure>",ScrollAll)
Je voudrais lier la molette de la souris à la barre de défilement afin que l'utilisateur puisse faire défiler le cadre sans avoir à utiliser les boutons fléchés de la barre de défilement. Après avoir regardé autour de moi, j'ai ajouté une liaison à mon canvas1
comme ça
self.frame1.bind("<MouseWheel>", self.OnMouseWheel)
Voici la fonction:
def OnMouseWheel(self,event):
self.scrollbar1.yview("scroll",event.delta,"units")
return "break"
Mais la barre de défilement ne bouge pas lorsque j'utilise la molette de la souris. Est-ce que quelqu'un peut m'aider avec ça? Tout ce que je veux, c'est que lorsque l'utilisateur utilise la molette de la souris (à l'intérieur de la zone du cadre/sur la barre de défilement), la toile doit automatiquement défiler vers le haut ou vers le bas.
La solution la plus simple est peut-être de créer une liaison globale pour la roue de la souris. Il se déclenchera alors quel que soit le widget sous la souris ou quel widget a le focus clavier. Vous pouvez ensuite faire défiler la toile sans condition, ou vous pouvez être intelligent et déterminer laquelle de vos fenêtres doit défiler.
Par exemple, sur Windows, vous feriez quelque chose comme ceci:
self.canvas = Canvas(...)
self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
...
def _on_mousewheel(self, event):
self.canvas.yview_scroll(-1*(event.delta/120), "units")
Notez que self.canvas.bind_all
est un peu trompeur - vous devriez plus correctement appeler root.bind_all
mais je ne sais pas quoi ni comment vous définissez votre fenêtre racine. Quoi qu'il en soit, les deux appels sont synonymes.
Différences de plate-forme:
<MouseWheel>
et vous devez diviser event.delta
par 120 (ou un autre facteur selon la vitesse à laquelle vous souhaitez faire défiler)<MouseWheel>
et vous devez utiliser event.delta
sans modification<Button-4>
et <Button-5>
, et vous devez diviser event.delta
par 120 (ou un autre facteur selon la vitesse à laquelle vous souhaitez faire défiler)Il existe des solutions plus raffinées impliquant des événements virtuels et déterminant quelle fenêtre a le focus ou se trouve sous la souris, ou en passant la référence de la fenêtre de canevas à travers la liaison, mais j'espère que cela vous aidera à démarrer.
Sur la base de la réponse de @ BryanOakley, voici un moyen de faire défiler uniquement le widget focalisé (c'est-à-dire celui sur lequel vous avez actuellement le curseur de la souris).
Lier à <Enter>
et <Leave>
événements se produisant sur votre cadre défilant qui se trouve à l'intérieur d'un canevas, de la manière suivante (scrollframe
est le cadre qui se trouve à l'intérieur du canevas):
....
self.scrollframe.bind('<Enter>', self._bound_to_mousewheel)
self.scrollframe.bind('<Leave>', self._unbound_to_mousewheel)
return
def _bound_to_mousewheel(self, event):
self.canv.bind_all("<MouseWheel>", self._on_mousewheel)
def _unbound_to_mousewheel(self, event):
self.canv.unbind_all("<MouseWheel>")
def _on_mousewheel(self, event):
self.canv.yview_scroll(int(-1*(event.delta/120)), "units")
Pour se débarrasser du facteur étrange 120, nous pourrions simplement regarder le signe de la valeur event.delta. Cela facilite l'utilisation du même gestionnaire sous Windows, Linux et Mac OS.
# Mouse wheel handler for Mac, Windows and Linux
# Windows, Mac: Binding to <MouseWheel> is being used
# Linux: Binding to <Button-4> and <Button-5> is being used
def MouseWheelHandler(event):
global count
def delta(event):
if event.num == 5 or event.delta < 0:
return -1
return 1
count += delta(event)
print(count)
import tkinter
root = tkinter.Tk()
count = 0
root.bind("<MouseWheel>",MouseWheelHandler)
root.bind("<Button-4>",MouseWheelHandler)
root.bind("<Button-5>",MouseWheelHandler)
root.mainloop()
Ce lien vous donne un exemple d'utilisation de la molette de défilement.
J'espère que ça aide!
# explore the mouse wheel with the Tkinter GUI toolkit
# Windows and Linux generate different events
# tested with Python25
import Tkinter as tk
def mouse_wheel(event):
global count
# respond to Linux or Windows wheel event
if event.num == 5 or event.delta == -120:
count -= 1
if event.num == 4 or event.delta == 120:
count += 1
label['text'] = count
count = 0
root = tk.Tk()
root.title('turn mouse wheel')
root['bg'] = 'darkgreen'
# with Windows OS
root.bind("<MouseWheel>", mouse_wheel)
# with Linux OS
root.bind("<Button-4>", mouse_wheel)
root.bind("<Button-5>", mouse_wheel)
label = tk.Label(root, font=('courier', 18, 'bold'), width=10)
label.pack(padx=40, pady=40)
root.mainloop()
Si vous êtes intéressé
#listbox scrollbar
from tkinter import *
root = Tk()
def scrolllistbox2(event):
listbox2.yview_scroll(int(-1*(event.delta/120)), "units")
scrollbar = Scrollbar(root)
#scrollbar.pack(side=RIGHT, fill=Y)
listbox = Listbox(root)
listbox.pack()
for i in range(100):
listbox.insert(END, i)
# attach listbox to scrollbar
listbox.config(yscrollcommand=scrollbar.set)
listbox.bind("<MouseWheel>", scrolllistbox2)
listbox2 = Listbox(root)
listbox2.pack()
for i in range(100):
listbox2.insert(END, i+100)
listbox2.config(yscrollcommand=scrollbar.set)
#scrollbar.config(command=listbox.yview)
root.mainloop()