Kivy:在更新功能中操作动态创建的小部件

时间:2015-01-05 02:30:31

标签: python-3.x layout kivy

我正在尝试扩展Nykakin提供的答案here中的代码,其中小部件在Kivy中动态定义,动态分配ID,然后根据ID进行操作。

'结束游戏'是通过根据ID改变小部件的位置来实现一些基本的2D物理。

我无法从更新功能(内联错误)中“移动”窗口小部件树。

有可能做这样的事吗?

以下是代码:

#code begins here
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.stacklayout import StackLayout
from kivy.uix.button import Button 
from kivy.uix.label import Label 
from kivy.clock import Clock
from kivy.factory import Factory

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

        button = Button(text="Print IDs", id="PrintIDsButton")
        button.bind(on_release=self.print_label)
        self.add_widget(button)

        # crate some labels with defined IDs
        for i in range(5):
            self.add_widget(Button(text=str(i), id="button no: " + str(i)))

        # update moved as per inclement's recommendation
        Clock.schedule_interval(MyApp.update, 1 / 30.0)

    def print_label(self, *args):
        children = self.children[:]
        while children:
            child = children.pop()
            print("{} -> {}".format(child, child.id))
            # we can change label properties from here! Woo!
            children.extend(child.children)
            if child.id == "PrintIDsButton":
                child.text = child.text + " :)"

class MyApp(App):
    def build(self):
        return MyWidget()

    def update(self, *args):
        #ERROR# AttributeError: 'float' object has no attribute 'root'
        children = self.root.children[:]

        #ERROR# TypeError: 'kivy.properties.ListProperty' object is not subscriptable
        #children = MyWidget.children[:]
        #while children:
        #    child = children.pop()
        #    print("{} -> {}".format(child, child.id))
        #    children.extend(child.children)

        #ERROR#  TypeError: 'kivy.properties.ListProperty' object is not iterable
        #for child in MyWidget.children:
        #    print("{} -> {}".format(child, child.id))
if __name__ == '__main__':
    MyApp().run()
  • Windows 7 SP1
  • Kivy 1.8.0 / Python 3.3

如果我的术语不正确,我道歉! (谢谢你的时间)

2 个答案:

答案 0 :(得分:2)

children = MyWidget.children[:]

MyWidget是类本身,而不是它的实例,因此子项是ListProperty对象而不是您想要的实际列表。

您希望MyWidget实例的子项是您的根窗口小部件self.root.children

另外,您可以在课程级别安排更新功能;我认为这是不好的做法,并可能导致微妙的错误。相反,在小部件的__init__方法中执行此操作会更为正常。

答案 1 :(得分:0)

所以将更新功能放在' MyWidget'然后访问' MyWidget'中的元素。通过调用self.children工作!

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.stacklayout import StackLayout
from kivy.uix.button import Button 
from kivy.uix.label import Label 
from kivy.clock import Clock
from kivy.factory import Factory

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

        button = Button(text="Print IDs", id="PrintIDsButton")
        button.bind(on_release=self.print_label)
        self.add_widget(button)

        # crate some labels with defined IDs
        for i in range(5):
            self.add_widget(Button(text=str(i), id="button no: " + str(i)))

        # update moved as per inclement's recommendation
        Clock.schedule_interval(self.update, 1 / 5.0)

    def print_label(self, *args):
        children = self.children[:]
        while children:
            child = children.pop()
            print("{} -> {}".format(child, child.id))
            # Add smiley by ID
            children.extend(child.children)
            if child.id == "PrintIDsButton":
                child.text = child.text + " :)"

    def update(self, *args):
        children = self.children[:]
        while children:
            child = children.pop()
            # remove smiley by ID
            if child.id == "PrintIDsButton":
                child.text  = "Print IDs"

class MyApp(App):
    def build(self):
        return MyWidget()

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

再次感谢恶意!