[英]Tkinter how to bind B1-Motion to Combobox
所以我在平板電腦上的應用程序中有一個組合框,我想制作它以便我可以拖動組合框向下滾動它。
到目前為止,我有這個功能:
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"
這適用於 Text 小部件(我需要它的大多數小部件),但我只知道如何用這個綁定組合框:
book_drop_down.bind("<<ComboboxSelected>>", tablet_drag_y)
我不知道如何將任何類型的動作綁定到組合框,我將如何去做?
您的問題(和解決方案)與此問題有點相似。 因此,那里的提示和想法也適用於您的問題。
首先,像您描述的這樣的功能已經存在:當您在列表邊界進行 b1 移動時 - 列表會自動滾動。 但是好吧,讓我們自己實現一些東西。
首先,我們需要理解組合框不是什么,而是條目和列表框小部件的組合,我們需要一個部分,即列表框(彈出窗口)。 幸運的是,有一個原生函數可以讓你把它撕掉:
popdown = combobox.tk.eval('ttk::combobox::PopdownWindow %s' % combobox)
之后,當我們的組合框被映射時,您可以自由地將某些內容綁定到該小部件:
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)
再詳細說明一點: popdown
是頂級窗口,它在您單擊組合框時從字面上彈出, f
是列表框的框架容器,而l
- 實際列表框,其中包含您的值。 看起來很簡單。
所以讓我們編碼一些東西:
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()
想法很簡單:獲取一個決策項,即中間列表框,然后根據當前元素的位置決定向上或向下滾動。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.