Kivy:为什么__init__中的孩子不可见?

时间:2015-07-28 17:52:54

标签: python kivy children init

我在这里有一个简单的演示应用程序,名为" question"。它包含一个标签和两个按钮。标签上的文字必须根据我按下的按钮而改变。请看一下:

enter image description here

真的没那么多。

适用于以下代码:

question.kv

#:kivy 1.9.0

<NormalKey>:

<Keyboard>:

    BoxLayout:
        orientation: "horizontal"

        NormalKey:
            id:          key_A
            text:       "A"
            on_release:  root.key_released(self.text)

        NormalKey:
            id:          key_B        
            text:       "B"
            on_release: root.key_released(self.text)

<MainPanel>:
    BoxLayout:
        orientation: "vertical"

        Label:
            id:    label_1
            text: "This text will change"

        Keyboard:
            linked_label: label_1

question.py

from kivy.app           import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button    import Button
from kivy.uix.label     import Label    

class NormalKey(Button):
    def __init__( self, **kwargs ):
        super(NormalKey, self).__init__(**kwargs)

class Keyboard(BoxLayout):
    def __init__(self, **kwargs):
        super(Keyboard, self).__init__(**kwargs)

        print self           # -->
        print self.children  # --> DOES NOT PRINT CHILDREN HERE
        print self.ids       # -->  

    def key_released(self, value):
        self.linked_label.text = value    

        print self           # -->
        print self.ids       # --> BUT PRINTS CHILDREN HERE 
        print self.children  # --> 


class MainPanel(BoxLayout):
    pass

class QuestionApp(App):
    def build(self):
        return MainPanel()

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

正如您所看到的,我的课程NormalKey来自Button,而我Keyboard来自BoxLayout

Keyboard里面有两个孩子,两个NormalKey个,因此有两个孩子。但是,在__init__中,Keyboard似乎没有意识到它们,但在另一个函数中,key_released在上面的例子中,儿童显然存在: - (

任何人都可以解释为什么在__init__中看不到孩子,如果有办法以某种方式看到他们,请访问它们吗?

由于正在构建Keyboard,可能无法访问子项。如果是这种情况,我可以以某种方式创建一个在构建小部件后立即调用的函数吗?

1 个答案:

答案 0 :(得分:0)

Keyboard__init__方法中不存在子项,因为此方法仅创建窗口小部件的基础,稍后将由其父级调用其add_widget方法填充。您可以在添加新子项时覆盖此方法以观察:

class Keyboard(BoxLayout):
    def add_widget(self, widget, *args):
        super(Keyboard, self).add_widget(widget, *args)
        print(widget)

您可以做的另一件事是观察children属性 - 每次添加新子项时都会调用方法on_children,带来更新版本的列表:

class Keyboard(BoxLayout):
    def on_children(self, obj, children):
        print(children)

最后,如果您希望在创建整个Keyboard对象后调用方法,则可以将该对象绑定到ObjectProperty并在其父类中观察它:

Builder.load_string("""

# ...

<MainPanel>:
    keyboard: keyboard

    BoxLayout:
        orientation: "vertical"

        Label:
            id:    label_1
            text: "This text will change"

        Keyboard:
            linked_label: label_1
            id: keyboard
""")

class MainPanel(BoxLayout):
    keyboard = ObjectProperty(None)

    def on_keyboard(self, panel, keyboard):
        print(keyboard)
        print(list(keyboard.ids))
        print(keyboard.children)

所有这些方法都会显示Keyboard对象只有一个子项BoxLayout,因为它实际上是该对象的唯一子项:

<Keyboard>:

    BoxLayout:
        orientation: "horizontal"

您不想在BoxLayout对象中添加Keyboard,因为此对象本身已经是BoxLayout(作为此类的后代)。您在BoxLayout内基本上有一个BoxLayout。我相信这就是你的意思:

<Keyboard>:
    orientation: "horizontal"

    NormalKey:
        id:          key_A
        text:       "A"
        on_release:  root.key_released(self.text)

    NormalKey:
        id:          key_B        
        text:       "B"
        on_release: root.key_released(self.text)