desplazamiento barra python binding tkinter scrollbar mousewheel

python - barra - tkinter scrollbar



Python tkinter enlace mousewheel to scrollbar (4)

Tengo este marco con capacidad de desplazamiento (marco dentro del lienzo en realidad).

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)

Me gustaría unir la rueda del mouse a la barra de desplazamiento para que el usuario pueda desplazarse hacia abajo en el marco sin tener que usar los botones de flecha en la barra de desplazamiento. Después de mirar alrededor, agregué un enlace a mi canvas1 como este

self.frame1.bind("<MouseWheel>", self.OnMouseWheel)

Esta es la función:

def OnMouseWheel(self,event): self.scrollbar1.yview("scroll",event.delta,"units") return "break"

Pero la barra de desplazamiento no se mueve cuando uso la rueda del ratón. Puede alguien ayudarme con esto? Todo lo que quiero es que cuando el usuario usa la rueda del mouse (dentro del área del marco / en la barra de desplazamiento), el lienzo se desplace hacia arriba o hacia abajo automáticamente.


Este enlace le da un ejemplo de cómo usar la rueda de desplazamiento.

http://www.daniweb.com/software-development/python/code/217059/using-the-mouse-wheel-with-tkinter-python

¡Espero que esto ayude!

# 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()


Para deshacernos del factor 120 extraño, solo podemos mirar el signo del valor event.delta. Esto facilita el uso del mismo controlador en Windows, Linux y 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()


Quizás la solución más simple es hacer un enlace global para la rueda del ratón. Entonces se activará sin importar qué widget esté bajo el mouse o qué widget tenga el foco del teclado. Luego puede desplazar incondicionalmente el lienzo, o puede ser inteligente y averiguar cuál de sus ventanas debe desplazarse.

Por ejemplo, en windows harías algo como esto:

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")

Tenga en cuenta que self.canvas.bind_all es un poco engañoso: más bien debería llamar root.bind_all pero no sé qué o cómo define su ventana raíz. En cualquier caso, las dos llamadas son sinónimos.

Diferencias de plataforma:

  • En Windows, se une a <MouseWheel> y necesita dividir event.delta por 120 (o algún otro factor dependiendo de qué tan rápido quiera el desplazamiento)
  • en OSX, se enlaza con <MouseWheel> y necesita usar event.delta sin modificación
  • en los sistemas X11, debe enlazar a <Button-4> y <Button-5> , y debe dividir event.delta por 120 (o algún otro factor dependiendo de qué tan rápido quiera desplazarse)

Hay soluciones más refinadas que involucran eventos virtuales y determinan qué ventana tiene el foco o está debajo del mouse, o pasando la referencia de la ventana del lienzo a través del enlace, pero esperamos que esto le ayude a comenzar.


Sobre la base de la respuesta de @ BryanOakley, aquí hay una forma de desplazar solo el widget enfocado (es decir, el cursor sobre el que se encuentra el cursor).

Enlazar a <Enter> y <Leave> eventos que ocurren en su marco desplazable que se encuentra dentro de un lienzo, de la siguiente manera (el marco de scrollframe es el marco que está dentro del lienzo):

.... 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")