首页 > 解决方案 > 阻止在 Windows 上运行的 Python 中的默认列表框滚动

问题描述

我的环境是 Python 2.7,在 Windows 7 上运行。

当我创建一个带有两个滚动列表框的 Tkinter 窗口时,默认行为是 Windows 会将鼠标滚轮操作指向其中任何一个具有焦点的操作。鼠标滚轮的每个增量向上/向下移动 4 行。当焦点离开列表框时,它停止响应鼠标滚轮。

最终,我希望用我自己的绑定完全替换这种行为。我已经为此编写了代码,它产生了我想要的新自定义响应,但问题是默认行为仍然存在,基于具有焦点的列表框。无论我尝试什么,我似乎都无法阻止它。

这是一个简化的代码示例来说明。我期望我与<FocusIn>事件的绑定(使用它的return 'break'行)会阻止默认的鼠标滚轮响应,但仍然会发生。我也尝试拦截该<<ListboxSelect>>事件,但这也没有阻止它。当我bind_all参加<Mousewheel>活动时,它甚至没有帮助;不知何故,默认响应仍然被触发。

import Tkinter as tk

#Root window
root = tk.Tk()

#Widgets
ctrl1 = tk.StringVar()
vsb1 = tk.Scrollbar(root,
                    orient=tk.VERTICAL)
lst1 = tk.Listbox(root,
                  width=20,height=10,
                  listvariable=ctrl1,
                  activestyle='dotbox',
                  yscrollcommand=vsb1.set)
vsb1.config(command=lst1.yview)

ctrl2 = tk.StringVar()
vsb2 = tk.Scrollbar(root,
                    orient=tk.VERTICAL)
lst2 = tk.Listbox(root,
                  width=20,height=10,
                  listvariable=ctrl2,
                  activestyle='dotbox',
                  yscrollcommand=vsb2.set)
vsb2.config(command=lst2.yview)

#Geometry
lst1.grid(row=0,column=0,sticky=tk.NSEW,padx=(5,0),pady=5)
vsb1.grid(row=0,column=1,sticky=tk.NS,padx=(0,5),pady=5)
lst2.grid(row=0,column=2,sticky=tk.NSEW,padx=(15,0),pady=5)
vsb2.grid(row=0,column=3,sticky=tk.NS,padx=(0,5),pady=5)

#Bindings
def focusIn1(*args):
    print 'Focus in 1'
    return 'break'

def focusIn2(*args):
    print 'Focus in 2'
    return 'break'

lst1.bind('<FocusIn>',focusIn1)
lst2.bind('<FocusIn>',focusIn2)

#Dummy listbox content
ctrl1.set('Entry-index-00 Entry-index-01 Entry-index-02 Entry-index-03 '+ \
         'Entry-index-04 Entry-index-05 Entry-index-06 Entry-index-07 '+ \
         'Entry-index-08 Entry-index-09 Entry-index-10 Entry-index-11 '+ \
         'Entry-index-12 Entry-index-13 Entry-index-14 Entry-index-15 '+ \
         'Entry-index-16 Entry-index-17 Entry-index-18 Entry-index-19 <end-of-queue>')

ctrl2.set('Entry-index-00 Entry-index-01 Entry-index-02 Entry-index-03 '+ \
         'Entry-index-04 Entry-index-05 Entry-index-06 Entry-index-07 '+ \
         'Entry-index-08 Entry-index-09 Entry-index-10 Entry-index-11 '+ \
         'Entry-index-12 Entry-index-13 Entry-index-14 Entry-index-15 '+ \
         'Entry-index-16 Entry-index-17 Entry-index-18 Entry-index-19 <end-of-queue>')

#Begin app
tk.mainloop()

我需要拦截其他一些事件吗?还是我需要使用一些不同的方法来阻止默认的鼠标滚轮响应?

(以防万一......我的目标是让一个列表框或另一个独立的单行滚动,仅基于鼠标指针是否在该列表框中。由于所描述的问题,如果(比如说)列表框 #1 具有焦点并且指针位于列表框 #2 上,它们会随着鼠标滚轮滚动滚动,其中 #2 一次滚动一行,而 #1 一次滚动 4 行。如果我切换并指向 #1,它会自行滚动,但它仍然一次滚动 4 行而不是 1 行。)

编辑:引用<MouseWheel>事件的绑定,但仍然无法阻止默认滚动行为。我用它代替了<FocusIn>事件。

#Bindings
def scrollBlock(*args):
    print "Blocking scrolling (except it won't)"
    return "break"

root.bind_all('<MouseWheel>',scrollBlock)

标签: python-2.7tkinterlistbox

解决方案


推荐阅读