Python tkinter привязывает колесико мыши к полосе прокрутки - программирование
Подтвердить что ты не робот

Python tkinter привязывает колесико мыши к полосе прокрутки

У меня есть этот прокручиваемый кадр (кадр внутри холста на самом деле).

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)

Я хотел бы привязать колесо мыши к полосе прокрутки, чтобы пользователь мог прокручивать рамку без необходимости использовать кнопки со стрелками на полосе прокрутки. Осмотревшись, я добавил привязку к моему canvas1, как это.

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

Это функция:

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

Но полоса прокрутки не перемещается, когда я использую колесико мыши. Кто-нибудь может мне с этим помочь? Все, что я хочу, - это когда пользователь использует колесико мыши (внутри области рамки/на полосе прокрутки), холст должен автоматически прокручиваться вверх или вниз.

4b9b3361

Ответ 1

Возможно, самым простым решением является создание глобальной привязки для колесика мыши. Затем он будет запускаться независимо от того, какой виджет находится под мышью или какой виджет имеет фокус клавиатуры. Затем вы можете безоговорочно прокручивать холст, или вы можете быть умным и выяснить, какие из ваших окон должны прокручиваться.

Например, в окнах вы делаете что-то вроде этого:

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

Обратите внимание, что self.canvas.bind_all немного вводит в заблуждение - вы более правильно должны вызывать root.bind_all, но я не знаю, как и как вы определяете свое корневое окно. Несмотря на это, два вызова являются синонимами.

Различия между платформами:

  • В Windows вы привязываетесь к <MouseWheel>, и вам нужно разделить event.delta на 120 (или какой-либо другой фактор в зависимости от того, насколько быстро вы хотите прокрутить)
  • в OSX, вы привязываетесь к <MouseWheel>, и вам нужно использовать event.delta без изменений
  • в системах X11 вам необходимо привязать к <Button-4> и <Button-5>, и вам нужно разделить event.delta на 120 (или какой-либо другой фактор в зависимости от того, насколько быстро вы хотите прокручивать)

Есть более совершенные решения, связанные с виртуальными событиями, и определение того, какое окно имеет фокус или находится под мышью, или передавая ссылку на окно холста через привязку, но, надеюсь, это поможет вам начать.

Ответ 2

Основываясь на ответе @BryanOakley, вот способ прокрутки только сфокусированного виджета (то есть того, на котором у вас есть курсор мыши в данный момент).

Привяжите к <Enter> и <Leave> события, происходящие на вашем прокручиваемом кадре, который находится внутри холста, следующим образом (scrollframe - это рамка, которая находится внутри холста):

    ....

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

Ответ 3

Эта ссылка дает вам пример того, как использовать колесо прокрутки.

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

Надеюсь, это поможет!

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

Ответ 4

Чтобы избавиться от странного фактора 120, мы могли бы просто взглянуть на знак значения event.delta. Это упрощает использование одного и того же обработчика под Windows, Linux и 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()

Ответ 5

Если вы заинтересованы

Как прокрутить 2 списка одновременно

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