【问题标题】:Accessing children of children's ids in KIvy在 KIvy 中访问孩子 ID 的孩子
【发布时间】:2017-02-26 11:17:14
【问题描述】:

如果图片太大,请见谅

好的。所以here's my complete code。它是中等大小的,因此仅供参考 - 不需要理解代码。

因此,如果我想在 Python 中访问 Layout 中的 Button()、Label() 或 TextInput() 对象,我只需执行 self.ids.object_name.property_of_object。

但是,假设我有一个 ScreenManager(),该 ScreenManager() 中有一个 Screen(),该屏幕对象中有一个自定义布局 MyCustomLayout()。就我能够得到的结果而言——我无法从 Screen() 的 Python 代码中的 MyCustomLayout() 中获取 id。

即假设在 MyCustomLayout() 中有一个按钮的 id,my_button。我想更改文本。

如果我在 MyCustomLayout() 类下,这将起作用:

self.ids.my_button.text = 'My new text!'

但是假设我在 MyScreen() 中,其中包含 MyCustomLayout()。我没能得到:

self.ids.my_button.text doesn't work
self.ids.my_custom_layout.my_button.text doesn't work

事实上,self.ids 返回 {}。由于某种原因,它甚至没有填充 ObservableDict。

但是,无论如何。我想我要说的是这个。如果我想访问自定义小部件的孩子:

  1. 在屏幕对象内
  2. 在 Python 中
  3. 在 MyScreen() 类下

我该怎么做?

谢谢!

加分:告诉我你是怎么知道这件事的!

【问题讨论】:

    标签: python kivy


    【解决方案1】:

    您可以在 kvlang 中为对象指定一个 id。 id: mybutton
    在以下示例中,我将按钮的文本设置为第一个屏幕输入时的随机数。
    在第二个屏幕中,我只是在输入时打印该屏幕及其子屏幕中的所有 id。

    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.lang import Builder
    from kivy.uix.boxlayout import BoxLayout
    from random import choice
    
    Builder.load_string('''
    
    
    <MyCustomLayout1>:
        Button:
            id: mybutton
            text: "Goto 2"
            on_release: app.sm.current = "screen2"
    
    
    <MyCustomLayout2>:
        Button:
            id: mybutton
            text: "Goto 1"
            on_release: app.sm.current = "screen1"
    
    
    <Screen1>:
        MyCustomLayout1:
            id: mylayout
    
    <Screen2>:
        MyCustomLayout2:
            id: mylayout
    
    ''')
    
    
    class Screen1(Screen):
    
        def on_enter(self,*args):
            self.ids.mylayout.ids.mybutton.text = str(choice(range(100)))
    
    
    class Screen2(Screen):
    
        def on_enter(self,*args):
            print(self.ids)
            print(self.ids.mylayout.ids)
    
    
    class MyCustomLayout1(BoxLayout):
        pass
    
    class MyCustomLayout2(BoxLayout):
        pass
    
    
    class MyApp(App):
        def build(self):
            self.sm = ScreenManager()
            self.sm.add_widget(Screen1(name='screen1'))
            self.sm.add_widget(Screen2(name='screen2'))
            return self.sm
    
    
    MyApp().run()
    

    当你嵌套对象时,你可以做obj.ids.obj.ids等等。
    即使这不是问题的一部分,我也可以提一下,对于从 boxlayout 访问屏幕管理器,将屏幕管理器设置为 App 类的属性是一个好主意。这样你就可以在 kvlang 中将它命名为 app.sm

    您可以通过询问我从哪里了解到这一点来结束您的问题。
    好吧,您做对了,只是没有正确嵌套。我从 kivy 的 api 参考 kvlang 中了解了 kvlang,但我不记得它是否对嵌套说了很多。但希望在这个例子中,这似乎是一种合乎逻辑的方式。

    【讨论】:

    • 啊,很高兴你这样回答。让我有机会更具体地说明我正在询问的内容。让我们使用您的代码,但修改 BoxLayout 部分,如下所示——要点:gist.github.com/Crowbrammer/d78ea1a3491db095021bbabc4744b99b
    • 照原样,在屏幕中实例化自定义类会为“mybutton”产生 KeyError。如果我取出第 40-41 行,我会得到一个 AttributeError--'MyCustomLayout1' has no attribute 'manager'(它没有)。所以,问题是,我们如何让这个带有自定义类的新代码像您的原始代码一样工作?
    • @crowbarProgramming 啊哈 :) 我去看看
    • @crowbarProgramming 更新了代码。也会更新一下答案文本
    • 哦,那是史诗。我感到如释重负,并且觉得我现在有了 Kivy 的控制感更强。谢谢 - 好吧,当之无愧的复选标记
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    • 2020-08-12
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多