Python Kivy:在屏幕上动态添加小部件

时间:2017-08-14 11:45:11

标签: python kivy kivy-language

从python代码(动态地)向屏幕添加小部件的好方法是什么?

我的目标是拥有两个主要的'屏幕。第二个屏幕的内容取决于主屏幕上选择的内容。为了简单起见,可以将该内容看作可变数量的按钮(所有内容,例如存储在数据库中并独立更新的按钮数量,背景图像等)。所以我想象的逻辑如下:当按下MainScreen按钮时,我进入数据库并通过按键N'按钮N'并以自定义Button / Label小部件的形式在第二个屏幕上显示它。如果需要,我还想回到MainScreen中选择其中的另一个按钮。

假设我有两个屏幕,其中静态图形在KV文件中定义:

<MainScreen>
    BoxLayout:
        orientation: "vertical"
        Label:
            text: "SELECT BUTTON"
        Button:
            on_press: root.show_buttons(self)
            text: "Button 1"
        Button:
            on_press: root.show_buttons(self)
            text: "Button 2"

<AnotherScreen>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: "Select BUTTON"
        Button: 
            on_press: root.manager.current = 'Main'
            text: "BACK"

MainScreen是完全静态的。按下按钮时,我需要调用AnotherScreen并根据按下的按钮向其添加内容。 我试图按照以下方式(并且失败):

class MainScreen(Screen):
    def show_buttons(self, btn):
        if btn.text == 'Button 1':
            another_screen.add_widget(Label(text="Button 1 pressed"))
            sm.current = "Another"
            return sm

class AnotherScreen(Screen):
    pass

class CoolApp(App):
    def build(self): 
        global sm
        sm = ScreenManager()
        main_screen = MainScreen(name='Main')
        sm.add_widget(main_screen)
        global another_screen
        another_screen = AnotherScreen(name='Another')
        sm.add_widget(another_screen)
        return sm


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

在这种情况下,动态窗口小部件another_screen.add_widget(Label(text="Button pressed"))被添加到一个屏幕上,该屏幕通过定义只能有一个孩子(已经在KV中定义)。我没有得到异常但我同时渲染了两个不同的小部件同样糟糕。

我想我需要向BoxLayout添加动态小部件,因为它是该屏幕的根小部件。但是,我不知道是否可以引用来自不同类的小部件,如果是,那是否合适?

谢谢!

1 个答案:

答案 0 :(得分:0)

一种方法是使用ID。

from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label

class MainScreen(Screen):
    first_btn_press = True
    def show_buttons(self, btn):
        if btn.text == 'Button 1':
            print(self.manager.ids)
            if self.first_btn_press:
                self.manager.ids.another.ids.box.add_widget(Label(text="Button 1 pressed"))
                self.first_btn_press = False
            self.manager.current = "another"

class AnotherScreen(Screen):
    pass

kv_str = Builder.load_string("""
ScreenManager:
    MainScreen:
        id: main
    AnotherScreen:
        id: another


<MainScreen>
    name: "main"
    BoxLayout:
        orientation: "vertical"
        Label:
            text: "SELECT BUTTON"
        Button:
            on_press: root.show_buttons(self)
            text: "Button 1"
        Button:
            on_press: root.show_buttons(self)
            text: "Button 2"

<AnotherScreen>:
    id: another
    name: "another"
    BoxLayout:
        id: box
        orientation: 'vertical'
        Label:
            text: "Select BUTTON"
        Button: 
            on_press: root.manager.current = 'main'
            text: "BACK"


""")



class CoolApp(App):
    def build(self):
        return kv_str


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

最后由你决定。另一种可能性是在ScreenManager中使用ObjectProperties或直接在app类中使用。上面的解决方案是我的首选方式。