FloatLayout 和 GridLayout 中的 kivy 下拉菜单不显示

kivy dropdown menu in FloatLayout and GridLayout doesnt show up

大家好,尝试创建一个带有下拉按钮的应用程序,但它似乎不起作用(完整的应用程序具有 GridLayout 和 7 行,示例中的这个 FloatLayout 是其中一行)我已经尝试过使用 GridLayout, BoxLayout 和 FloatLayout 仍然没有出现在应用程序中。知道这里出了什么问题吗?

.py 文件

class WindowManager(ScreenManager, Screen):
    TestMe = ObjectProperty(None)

text_lists = ['hi', 'nice one', 'another one']


class TestMe(Screen, FloatLayout):
    global text_lists
    main_button = ObjectProperty(None)
    selected_list = 'SELECTED'
    top_layout = ObjectProperty(None)
    top_layout = GridLayout(cols=4)

    def __init__(self, **kwargs):
        super(TestMe, self).__init__(**kwargs)
        self.dropdown = DropDown()
        self.create_drop_down()
        self.create_go_button()

    def create_drop_down(self):
        for list_name in text_lists:
            # When adding widgets, we need to specify the height manually
            # (disabling the size_hint_y) so the dropdown can calculate
            # the area it needs.

            btn = Button(text= list_name, size_hint_y=None, height=88, width=400, background_color=(41/255, 21/255, 228/255, 1))

            # for each button, attach a callback that will call the select() method
            # on the dropdown. We'll pass the text of the button as the data of the
            # selection.
            btn.bind(on_release=lambda btn: self.dropdown.select(btn.text),
                     on_press=lambda btn: self.select_list(btn.text))

            # then add the button inside the dropdown
            self.dropdown.add_widget(btn)

        # create a big main button
        self.main_button = Button(text='Choose A List', size_hint=(None, None), height=88, width=400, background_color=(41/255, 21/255, 228/255, 1))

        # show the dropdown menu when the main button is released
        # note: all the bind() calls pass the instance of the caller (here, the
        # mainbutton instance) as the first argument of the callback (here,
        # dropdown.open.).
        self.main_button.bind(on_release=self.dropdown.open)

        # one last thing, listen for the selection in the dropdown list and
        # assign the data to the button text.
        self.dropdown.bind(on_select=lambda instance, x: setattr(self.main_button, 'text', x))
        self.top_layout.add_widget(self.main_button)

    def create_go_button(self):
        go_btn = Button(text="Go!", size_hint=(None, None), height=88, width=400, background_color=(41/255, 21/255, 228/255, 1))
        self.top_layout.add_widget(go_btn)

    def select_list(self, selected):
        self.selected_list = selected

class MyTest(App):
    def build(self):
        return kv


if __name__ == '__main__':
    kv = Builder.load_file('test_kv.kv')

    MyTest().run()

test_kv.kv 文件

WindowManager:
    TestMe:

<TestMe>:
name: "testy"
id: testy
top_layout: top_layout
FloatLayout:
    Label:
        text: 'Test Screen'
        font: 'Aharoni'
        font_size: 24
        pos_hint: {"left": 0.45, "y": 0.45}
    GridLayout:
        pos_hint: {"top": 0.9}
        size_hint: 1, 0.8
        rows: 2
        spacing: 10
        padding: 10
        GridLayout:
            id: top_layout
            cols: 4
            Button:
                text: "Fun!"
            Label:
                text: "This is a test"
        Button:
            text: "Run!"

当我 运行 你的代码(必须添加一个 App class)时,大主按钮出现,并且按预期工作。但是 Button 和你的 light.png Image 一起出现在左下角。尝试稍微移动它,使其不与 Image 重叠。像这样:

    self.main_button = Button(text='Choose A List', size_hint=(None, None), height=88, width=140,
                              background_color=(41/255, 21/255, 228/255, 1), pos_hint={'center_x':0.5, 'y':0.4})

我还把 Choose A List 文本加宽了一点。

问题是您在 TestMe class 的 __init__() 方法中调用了 create_drop_down()create_go_button()。由于您还在 kv 中定义了 <TestMe>: 规则,因此存在冲突。根据有点不清楚的documentationkv规则是在__init__()是运行之后应用的。这意味着在其 __init__() 中添加到 TestMe 的任何 Widgets 将被 kv 规则中指定的 Widegets 覆盖。可能的解决方案是在 __init__() 方法或 kv 方法中添加 TestMe 的所有子项,或者将 Widgets 的添加移出 [=13] =] 方法。这是您的代码的修改版本,采用后一种方法:

class WindowManager(ScreenManager, Screen):
    TestMe = ObjectProperty(None)

text_lists = ['hi', 'nice one', 'another one']


class TestMe(Screen, FloatLayout):
    global text_lists
    main_button = ObjectProperty(None)
    selected_list = 'SELECTED'
    top_layout = ObjectProperty(None)
    #top_layout = GridLayout(cols=4)

    def __init__(self, **kwargs):
        super(TestMe, self).__init__(**kwargs)
        self.dropdown = DropDown()
        Clock.schedule_once(self.create_drop_down)
        Clock.schedule_once(self.create_go_button)
        # self.create_drop_down()
        # self.create_go_button()

    def create_drop_down(self, *args):
        for list_name in text_lists:
            # When adding widgets, we need to specify the height manually
            # (disabling the size_hint_y) so the dropdown can calculate
            # the area it needs.

            btn = Button(text= list_name, size_hint_y=None, height=88, width=400, background_color=(41/255, 21/255, 228/255, 1))

            # for each button, attach a callback that will call the select() method
            # on the dropdown. We'll pass the text of the button as the data of the
            # selection.
            btn.bind(on_release=lambda btn: self.dropdown.select(btn.text),
                     on_press=lambda btn: self.select_list(btn.text))

            # then add the button inside the dropdown
            self.dropdown.add_widget(btn)

        # create a big main button
        # self.main_button = Button(text='Choose A List', size_hint=(None, None), height=88, width=400, background_color=(41/255, 21/255, 228/255, 1))
        self.main_button = Button(text='Choose A List', background_color=(41/255, 21/255, 228/255, 1))

        # show the dropdown menu when the main button is released
        # note: all the bind() calls pass the instance of the caller (here, the
        # mainbutton instance) as the first argument of the callback (here,
        # dropdown.open.).
        self.main_button.bind(on_release=self.dropdown.open)

        # one last thing, listen for the selection in the dropdown list and
        # assign the data to the button text.
        self.dropdown.bind(on_select=lambda instance, x: setattr(self.main_button, 'text', x))
        self.top_layout.add_widget(self.main_button)

    def create_go_button(self, *args):
        # go_btn = Button(text="Go!", size_hint=(None, None), height=88, width=400, background_color=(41/255, 21/255, 228/255, 1))
        go_btn = Button(text="Go!", background_color=(41/255, 21/255, 228/255, 1))
        self.top_layout.add_widget(go_btn)

    def select_list(self, selected):
        self.selected_list = selected

class MyTest(App):
    def build(self):
        return kv

我已修改代码以使用 Clock.schedule_once() 调用 create 方法,以便在应用 kv 规则后发生。 我还删除了 size_hintsize 参数到 Buttons 创建以允许 GridLayout 调整它们的大小。我还注释掉了一些不必要的代码。