Kivy:如何正确绑定下拉菜单?
Kivy: How to bind dropdown opening properly?
我正在努力使 DropDown 打开正确绑定到选择按钮的释放。我试过使用这个:
selection_button.bind(on_release=drpdn.open)
当我创建多个 DropDown 时,绑定似乎相当随机地工作(一些 DropDown 打开其他不打开,我看不到其中的任何逻辑)。 然而它显示准确就像 Kivy documentation.
中的示例一样
我能够通过为 DropDown 打开创建我自己的回调函数来解决这个问题,我在其中传递选择按钮和 DropDown 实例(使用 functools.partial)并通过以下方式简单地打开 DropDown:
def open_dropdown(self, wid, drpdn, *largs):
drpdn.open(wid)
虽然这个解决方法有效,但它确实让我很困扰,因为我显然没有正确理解绑定和回调的工作原理。谁能指出我正确的方向?我预计 selection_button.bind(on_release=drpdn.open)
将选择按钮传递给 DropDown 打开方法,DropDown 在其上打开,但显然它没有。最令人难以置信的是它似乎随机工作(例如,当我创建四个选择按钮时,其中一些会工作)。
这是我的测试应用程序代码。 create_dropdown
方法完美运行,而 create_dropdown2
方法会导致奇怪的行为(实际上只有最后一个 DropDown 打开)。
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
不是局部变量。
我正在努力使 DropDown 打开正确绑定到选择按钮的释放。我试过使用这个:
selection_button.bind(on_release=drpdn.open)
当我创建多个 DropDown 时,绑定似乎相当随机地工作(一些 DropDown 打开其他不打开,我看不到其中的任何逻辑)。 然而它显示准确就像 Kivy documentation.
中的示例一样我能够通过为 DropDown 打开创建我自己的回调函数来解决这个问题,我在其中传递选择按钮和 DropDown 实例(使用 functools.partial)并通过以下方式简单地打开 DropDown:
def open_dropdown(self, wid, drpdn, *largs):
drpdn.open(wid)
虽然这个解决方法有效,但它确实让我很困扰,因为我显然没有正确理解绑定和回调的工作原理。谁能指出我正确的方向?我预计 selection_button.bind(on_release=drpdn.open)
将选择按钮传递给 DropDown 打开方法,DropDown 在其上打开,但显然它没有。最令人难以置信的是它似乎随机工作(例如,当我创建四个选择按钮时,其中一些会工作)。
这是我的测试应用程序代码。 create_dropdown
方法完美运行,而 create_dropdown2
方法会导致奇怪的行为(实际上只有最后一个 DropDown 打开)。
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
不是局部变量。