Kivy:如何正确地绑定下拉菜单打开?



我正在努力使DropDown打开绑定正确地释放选择按钮。我试着用这个:

selection_button.bind(on_release=drpdn.open)

当我创建多个下拉菜单时,绑定似乎随机工作(一些下拉菜单打开其他不打开,我看不到其中的任何逻辑)。然而,它在Kivy文档中的示例中显示的与此完全相同。

我能够克服这个问题,通过创建我自己的回调函数为DropDown打开,我传递选择按钮和DropDown实例(使用functools.partial),并打开DropDown只需:

def open_dropdown(self, wid, drpdn, *largs):
drpdn.open(wid)

虽然这个解决方法有效,但它确实困扰着我,因为我显然没有正确理解绑定和回调是如何工作的。有人能给我指个方向吗?我期望selection_button.bind(on_release=drpdn.open)将选择按钮传递给下拉打开方法,下拉打开它,但显然它没有。最令人难以置信的是,它似乎随机工作(例如,当我创建四个选择按钮时,其中一些将工作)。

这是我的测试应用程序代码。create_dropdown方法工作完美,而create_dropdown2方法导致奇怪的行为(只有最后一个下拉菜单实际打开)。

from functools import partial
from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class TestApp(App):
def create_dropdown(self, text, options):
selection_button = Button(text=text)
drpdn = DropDown()
for o in options:
btn = Button(text=o, size_hint_y=None, height=44)
btn.bind(on_release=partial(self.change_select,
selection_button,
btn.text
)
)
btn.bind(on_release=drpdn.dismiss)
drpdn.add_widget(btn)
selection_button.bind(on_release=partial(self.open_dropdown,
selection_button,
drpdn
)
)
return selection_button
def create_dropdown2(self, text, options):
selection_button = Button(text=text)
drpdn = DropDown()
for o in options:
btn = Button(text=o, size_hint_y=None, height=44)
btn.bind(on_release=partial(self.change_select,
selection_button,
btn.text
)
)
btn.bind(on_release=drpdn.dismiss)
drpdn.add_widget(btn)
selection_button.bind(on_release=drpdn.open)
return selection_button
def change_select(self, wid, text, *largs):
wid.text = text
def open_dropdown(self, wid, drpdn, *largs):
drpdn.open(wid)
def build(self):
root = BoxLayout(orientation="vertical")
for _ in range(3):
root.add_widget(self.create_dropdown("Works",
["yes", "no"]
)
)
for _ in range(4):
root.add_widget(self.create_dropdown2("Does not work",
["yes", "no"]
)
)
return root

if __name__ == '__main__':
TestApp().run()

在您的create_dropdown2()方法中,您将on_release绑定到本地变量(drpdn)。绑定创建了对drpdn的弱引用。这意味着当drpdn超出作用域时,绑定不会阻止它被删除和垃圾收集。然后,当按钮被释放时,on_release绑定的方法现在是None

create_dropdown()中的partial调用冻结了提供的参数,避免了超出作用域的问题。

注意,在文档中,dropdown不是一个局部变量。

最新更新