【问题标题】:Python Kivy: Dynamic addition of widgets to a screenPython Kivy:将小部件动态添加到屏幕
【发布时间】:2017-08-14 11:45:11
【问题描述】:

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

我的目标是拥有两个“主”屏幕。第二个屏幕的内容取决于在主屏幕上选择的内容。为简单起见,可以将此内容视为可变数量的按钮(所有内容,如按钮数量、背景图像等都存储在数据库中并独立更新)。所以我想象的逻辑如下:当按下 MainScreen 按钮时,我进入数据库并通过键“按钮 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 中添加动态小部件,因为它是该屏幕的根小部件。但是,我不知道是否可以引用不同类的小部件,如果可以,是否合适?

谢谢!

【问题讨论】:

    标签: python kivy kivy-language


    【解决方案1】:

    一种方法是使用 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。上面的解决方案是我的首选方式。

    【讨论】:

    • 谢谢!我也在尝试这种方法,但是问题是,如果我多次调用第二个屏幕,它将导致向其中添加多个相同的按钮。这就是我有“返回”按钮的原因:如果需要,我想返回主屏幕。如果我在返回后再次按下按钮“按钮 1”,我将有两个标签“按下按钮 1”。
    • 如果这不是您想要的行为,您可以简单地添加一个布尔值,一旦按下按钮和 if 子句就可以更改它,因此下次它只会切换屏幕。我可以在明天补充。
    • 还请在您的问题中添加更多详细信息。所以更容易理解你的目标是什么。
    • 我在帖子中添加了一些细节,不确定它是否澄清了一些事情?期待您的“布尔”解决方案,感谢您的帮助。
    • 我的意思是您可以轻松地创建和设置所有小部件。然后将小部件的不透明度设置为“不可见”的 0(假)或“可见”的 1(真)。您尝试做的所有事情都可以在 kv 和纯 Python 中完成。在 kv 中,您可以将 opacity: 添加到每个规则的末尾
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多