[英]Tkinter how to bind B1-Motion to Combobox
so I have a combobox in an app I am putting on a tablet, I'm wanting to make it so that I can drag on the combobox that it will scroll down it.所以我在平板电脑上的应用程序中有一个组合框,我想制作它以便我可以拖动组合框向下滚动它。
So far I have this function:到目前为止,我有这个功能:
def tablet_drag_y(event):
global last_y
if event.y_root-last_y>20 or event.y_root-last_y<-20:
last_y=event.y_root
event.widget.tag_remove(Tk.SEL, "1.0", Tk.END)
return "break"
event.widget.yview(Tk.SCROLL,-1*(event.y_root-last_y), "units")
last_y=event.y_root
event.widget.tag_remove(Tk.SEL, "1.0", Tk.END)
return "break"
This works on Text widgets (the majority of widgets I need this for), but I only know how to bind the combo box with this:这适用于 Text 小部件(我需要它的大多数小部件),但我只知道如何用这个绑定组合框:
book_drop_down.bind("<<ComboboxSelected>>", tablet_drag_y)
Idk how to bind any sort of motion to the combobox, how would I go about doing this?我不知道如何将任何类型的动作绑定到组合框,我将如何去做?
Your question (and solution) is little similar to this one .您的问题(和解决方案)与此问题有点相似。 Thus, tips and ideas from there apply to your problem as well.因此,那里的提示和想法也适用于您的问题。
First of all, such functionality like you described is already there: when you are on b1-movement at the borders of the list - the list is automatically scrolled.首先,像您描述的这样的功能已经存在:当您在列表边界进行 b1 移动时 - 列表会自动滚动。 But ok, let's implement something on our own.但是好吧,让我们自己实现一些东西。
To start with we need to comprehend that combobox is nothing, but a combo of entry and listbox widgets, and we need a part, that is a listbox (a popdown window).首先,我们需要理解组合框不是什么,而是条目和列表框小部件的组合,我们需要一个部分,即列表框(弹出窗口)。 Fortunately, there is a native function that allows you to tear it out:幸运的是,有一个原生函数可以让你把它撕掉:
popdown = combobox.tk.eval('ttk::combobox::PopdownWindow %s' % combobox)
After that your a free to bind something to that widget, when our combobox is mapped:之后,当我们的组合框被映射时,您可以自由地将某些内容绑定到该小部件:
class CustomBox(ttk.Combobox):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.bind('<Map>', self._handle_popdown_bind_on_initialisation)
def _handle_popdown_bind_on_initialisation(self, *args):
popdown = self.tk.eval('ttk::combobox::PopdownWindow %s' % self)
self._bind(('bind', '%s.f.l' % popdown), '<B1-Motion>', <callback_function>, None)
To elaborate a little more: popdown
is the toplevel window, that literally pops down on your click on the combobox, f
a frame-container for listbox, and l
- the actual listbox, which contains your values.再详细说明一点: popdown
是顶级窗口,它在您单击组合框时从字面上弹出, f
是列表框的框架容器,而l
- 实际列表框,其中包含您的值。 Looks simple.看起来很简单。
So let's code something:所以让我们编码一些东西:
import tkinter as tk
import tkinter.ttk as ttk
import random
import string
class CustomBox(ttk.Combobox):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# schedule bind to handle popdown
self.bind('<Map>', self._handle_popdown_bind_on_initialisation)
def _handle_popdown_bind_on_initialisation(self, *args):
# once combobox is drawn bind callback function
popdown = self.tk.eval('ttk::combobox::PopdownWindow %s' % self)
self._bind(('bind', '%s.f.l' % popdown), '<B1-Motion>', drag, None)
def insert_something_to_combobox(box, count=30):
# just to insert some random stuff
box['values'] = [gen_key() for _ in range(count)]
def gen_key(size=6, chars=string.ascii_uppercase + string.digits):
# just to generate some random stuff
return ''.join(random.choice(chars) for _ in range(size))
def drag(event):
# test-event for B1-Motion over popdown
# get index of the nearest item
nearest_item = root.tk.call(event.widget, 'nearest', event.y)
# get actual size of listbox
actual_size = root.tk.call(event.widget, 'size')
# get current boundary positions for listbox
current_yview = root.tk.call(event.widget, 'yview')
# get current boundary items
current_items = [int(fraction * actual_size) for fraction in current_yview]
# get decider-item for scrolling
decider_item = sum(current_items) // 2
# debug-configure current item
mouse_over_label.configure(text='B1 over item: %s' % root.tk.call(event.widget, 'get', nearest_item))
if nearest_item < decider_item:
# scroll-up
root.tk.call(event.widget, 'see', current_items[0] - 1)
elif nearest_item > decider_item:
# scroll-down
root.tk.call(event.widget, 'see', current_items[1] + 1)
root = tk.Tk()
mouse_over_label = tk.Label()
mouse_over_label.pack()
combo_box = CustomBox()
combo_box.pack()
insert_something_to_combobox(combo_box)
root.mainloop()
The idea is simple: get a decider item, that is half-way-thru listbox, and, depending on the position of the current element, decide to scroll up or down.想法很简单:获取一个决策项,即中间列表框,然后根据当前元素的位置决定向上或向下滚动。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.