这是Kivy中的错误吗? DropDown + ScreenManager 未按预期工作

Is it a bug in Kivy? DropDown + ScreenManager not working as expected

我在使用 ScreenManager 和 DropDown 时遇到可重现的困难,如果在使用 DropDown 的屏幕之前有屏幕的话。 我已经为此苦苦挣扎了好几天,因为我是初学者,所以我认为这是我的错。
我将代码分解为问题的核心,这样我的预期功能就丢失了。 Intended 是一个增量搜索字段,这样只有适当的选项才会显示在下拉列表中。这就是为什么我需要一个绑定到下拉按钮的输入小部件。我有一个解决方案,它只是不能像预期的那样与 screenmanager 一起工作。
请考虑此代码:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.textinput import TextInput
from kivy.properties import ListProperty, StringProperty
import re
from kivy.lang import Builder

Builder.load_string('''
<Intro>:
    BoxLayout:
        Button:
            text: 'Press to go to SecondScreen'
            font_size: '20px'
            on_release: root.manager.current = 'SecondScreen'
<SecondScreen>:
    ComboLayout:
        Label:
            text: "Dropdown on SecondScreen \n\n if ComboEdit.text doesn't have \n a non-empty string assigned \n code is broken!"
            font_size: '20px'
        ComboEdit:
            size_hint: .5, .5
            pos_hint: {'center':(.5, .5)}
            on_text: self.parent.on_text(self, args[1])
            text: 'X'                 ## <<<=== THIS IS NECESSARY, REALLY!?!
            font_size: '100px'
            multiline: False
''')

class ComboEdit(TextInput):
    options = ListProperty(('',))

    def __init__(self, **kw):
        ddn = self.drop_down = DropDown()
        ddn.bind(on_select=self.on_select)
        super(ComboEdit, self).__init__(**kw)

    def on_options(self, instance, value):
        ddn = self.drop_down
        ddn.clear_widgets()
        for option in value:
            but = Button(text=option,
                         size_hint_y=None,
                         height='36sp',
                         on_release=lambda btn: ddn.select(btn.text))
            ddn.add_widget(but)

    def on_select(self, instance, value):
        self.text = value

class ComboLayout(BoxLayout):
    def on_text(self, instance, value):
        instance.options = [str(i) for i in range(0,8)]
        instance.drop_down.open(instance)

class Intro(Screen):
    pass
class SecondScreen(Screen):
    pass

class BugDemoApp(App):
    def build(self):
        sm = ScreenManager()
        sm.add_widget(Intro(name='Intro'))
        sm.add_widget(SecondScreen(name='SecondScreen'))
        return sm

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

我偶然发现:我需要将一些非空字符串分配给 ComboEdit.text,如果不是 - 使其成为评论或分配“” - 我得到这个回溯:

   File "C:/Users/ORANG/PycharmProjects/waldi/playground/widgets.py", line 56, in on_text
     instance.drop_down.open(instance)
   File "C:\Kivy-1.9.0-py2.7-win32-x64\kivy27\kivy\uix\dropdown.py", line 215, in open
     'Cannot open a dropdown list on a hidden widget')
 kivy.uix.dropdown.DropDownException: Cannot open a dropdown list on a hidden widget

我的问题是:

1) 这可能是一个错误还是我在这里做错了什么?

2) 如果是bug,应该在哪里公布?

3) 目前对我来说最重要的是:现在用户必须手动从编辑字段中删除 ComboEdit.text 中的给定字符串,以用他自己的输入替换它。这太丑了。您有解决方法吗?是否可以选择虚拟文本,以便如果用户开始输入,它将立即被覆盖?

我试过这样做

   ComboEdit:
        ...
        focus: True
        select_all: True

但是没有效果?

任何关于错误的确认,任何绕过它的提示,任何我在这里做错的解释都将非常非常非常欢迎!

可以通过许多(更好的?)方式来完成,但这行得通。

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.textinput import TextInput
from kivy.properties import ListProperty, StringProperty
import re
from kivy.lang import Builder

Builder.load_string('''
<Intro>:
    BoxLayout:
        Button:
            text: 'Press to go to SecondScreen'
            font_size: '20px'
            on_release: root.manager.current = 'SecondScreen'
<SecondScreen>:
    ComboLayout:
        Label:
            text: "working?"
            font_size: '20px'
        ComboEdit:
            size_hint: .5, .5
            pos_hint: {'center':(.5, .5)}
            font_size: '100px'
            multiline: False
''')

class ComboEdit(TextInput):
    options = ListProperty([])

    def __init__(self, **kw):
        super(ComboEdit, self).__init__(**kw)
        self.ddn = DropDown()
        self.ddn.bind(on_select=self.on_select)

    def on_options(self, instance, value):

        for option in value:
            but = Button(text=option,
                         size_hint_y=None,
                         height='36sp',
                         on_release=lambda btn: self.ddn.select(btn.text))
            self.ddn.add_widget(but)

    def on_select(self, instance, value):
        self.text = value

    def on_text(self, instance, value):

        self.options = [str(i) for i in range(0,8)]
        if not self.get_root_window():
            return # do proceed if I'm not displayed <=> If have no parent
        self.ddn.open(self)


class ComboLayout(BoxLayout):
    pass

class Intro(Screen):
    pass

class SecondScreen(Screen):
    pass

class BugDemoApp(App):
    def build(self):
        sm = ScreenManager()
        sm.add_widget(Intro(name='Intro'))
        sm.add_widget(SecondScreen(name='SecondScreen'))
        return sm

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

希望对您有所帮助。