将多个Tkinter列表框一起滚动

Bob*_*obC 8 python listbox tkinter scrollbar mousewheel

我有多个Tkinter列表框,我使用一个滚动条滚动在一起,但我也喜欢它们一起滚动鼠标滚轮活动在任何列表框上.

这该怎么做?

我当前的代码基于此处讨论的最后一个模式:http://effbot.org/tkinterbook/listbox.htm 仅使用滚动条时工作正常,但是当使用鼠标滚轮时,列表框会独立滚动.

San*_*use 12

我知道这已经很老了,但我认为解决方案比这里提供的解决方案简单一些.假设您总是希望列表框一致,那么上面的两个答案甚至都不是完整的解决方案 - 通过箭头键更改选择将滚动一个列表框而不是另一个列表框.

所以,看看答案,我问 - 为什么他们不挂钩yscrollcommand回调而不是直接发送到滚动条?所以,我做到了这一点:

try:
    from Tkinter import *
except ImportError:
    from tkinter import *


class MultipleScrollingListbox(Tk):

    def __init__(self):
        Tk.__init__(self)
        self.title('Scrolling Multiple Listboxes')

        #the shared scrollbar
        self.scrollbar = Scrollbar(self, orient='vertical')

        #note that yscrollcommand is set to a custom method for each listbox
        self.list1 = Listbox(self, yscrollcommand=self.yscroll1)
        self.list1.pack(fill='y', side='left')

        self.list2 = Listbox(self, yscrollcommand=self.yscroll2)
        self.list2.pack(expand=1, fill='both', side='left')

        self.scrollbar.config(command=self.yview)
        self.scrollbar.pack(side='right', fill='y')

        #fill the listboxes with stuff
        for x in xrange(30):
            self.list1.insert('end', x)
            self.list2.insert('end', x)

    #I'm sure there's probably a slightly cleaner way to do it than this
    #Nevertheless - whenever one listbox updates its vertical position,
    #the method checks to make sure that the other one gets updated as well.
    #Without the check, I *think* it might recurse infinitely.
    #Never tested, though.
    def yscroll1(self, *args):
        if self.list2.yview() != self.list1.yview():
            self.list2.yview_moveto(args[0])
        self.scrollbar.set(*args)

    def yscroll2(self, *args):
        if self.list1.yview() != self.list2.yview():
            self.list1.yview_moveto(args[0])
        self.scrollbar.set(*args)

    def yview(self, *args):
        self.list1.yview(*args)
        self.list2.yview(*args)


if __name__ == "__main__":
    root = MultipleScrollingListbox()
    root.mainloop()
Run Code Online (Sandbox Code Playgroud)


Bry*_*ley 11

解决这个问题几乎相同的方式,你做了两个小部件连接到一个滚动条:对鼠标滚轮创建自定义绑定,并将这些绑定影响两个列表框,而不是只有一个.

唯一真正的诀窍是知道你根据平台获得鼠标轮的不同事件:windows和Mac获取<MouseWheel>事件,linux获取<Button-4><Button-5>事件.

这是一个例子,在我的Mac上使用python 2.5测试:

import Tkinter as tk

class App:
    def __init__(self):
        self.root=tk.Tk()
        self.vsb = tk.Scrollbar(orient="vertical", command=self.OnVsb)
        self.lb1 = tk.Listbox(self.root, yscrollcommand=self.vsb.set)
        self.lb2 = tk.Listbox(self.root, yscrollcommand=self.vsb.set)
        self.vsb.pack(side="right",fill="y")
        self.lb1.pack(side="left",fill="x", expand=True)
        self.lb2.pack(side="left",fill="x", expand=True)
        self.lb1.bind("<MouseWheel>", self.OnMouseWheel)
        self.lb2.bind("<MouseWheel>", self.OnMouseWheel)
        for i in range(100):
            self.lb1.insert("end","item %s" % i)
            self.lb2.insert("end","item %s" % i)
        self.root.mainloop()

    def OnVsb(self, *args):
        self.lb1.yview(*args)
        self.lb2.yview(*args)

    def OnMouseWheel(self, event):
        self.lb1.yview("scroll", event.delta,"units")
        self.lb2.yview("scroll",event.delta,"units")
        # this prevents default bindings from firing, which
        # would end up scrolling the widget twice
        return "break"

app=App()
Run Code Online (Sandbox Code Playgroud)

  • 我遇到了同样的问题。刚发现一件事。我创建了一个列表框列表,并使用for循环将相同事件绑定到每个列表框,并使用OnMouseWheel()中的另一个for循环遍历每个列表框。它与event.delta不兼容,因为列表框与鼠标移过的方向不同。只需说-(event.delta)即可解决。适用于Windows,Python 3.5.1 (2认同)