【问题标题】:Kivy: Manipulating dynamically created widgets in update functionKivy:在更新功能中操作动态创建的小部件
【发布时间】:2015-01-05 02:30:31
【问题描述】:

我正在尝试扩展 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

如果我的术语不正确,我深表歉意! (感谢您的宝贵时间)

【问题讨论】:

    标签: python-3.x layout kivy


    【解决方案1】:
    children = MyWidget.children[:]
    

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

    您想要的是作为您的根小部件的 MyWidget 实例的子代,self.root.children。

    此外,您可以在班级级别安排更新功能;我认为这是不好的做法,可能会导致细微的错误。在小部件的__init__ 方法中这样做会更正常。

    【讨论】:

    • 谢谢你的恶意!时钟计划更新功能根据您的建议移动。不过,如上所述,我仍然收到错误消息。
    【解决方案2】:

    因此,将更新函数放在“MyWidget”类中,然后通过调用 self.children 访问“MyWidget”中的元素就可以了!

    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()
    

    再次感谢恶意!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-22
      • 2012-05-09
      • 1970-01-01
      • 1970-01-01
      • 2018-09-23
      • 1970-01-01
      相关资源
      最近更新 更多