添加 - 删除kivy中的小部件

时间:2016-10-30 07:06:24

标签: python kivy

我在kivy中添加或删除小部件时遇到了一些困难。情况就是这样:

主窗体应包含三个小部件中的两个,Widget1,Widget2和Widget3。按下Widget1的按钮,应该删除Widget2并显示Widget3。

这是main.py文件:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.factory import Factory

class TableApp(App):

    def on_pause(self): return True

    def on_resume(self): pass

class Form(BoxLayout):
    def click(self, instance, arg):
        print 'this is the Form class'
        print 'this is my arg ... ', arg
        print 'this is the button pressed ... ', instance
        print 'these are the children of the Form class:', self.children
        Form().remove_widget(Widget2)
        Form().add_widget(Widget3)

class Widget1(BoxLayout):

    def click(self, instance, arg):
        print 'this is the Widget 1'
        print 'this is my arg ... ', arg
        print 'this is my instance', instance, '\n'
        Factory.Form().click(instance,arg)

class Widget2(BoxLayout):
    pass

class Widget3(BoxLayout):
    pass

if __name__ in ('__android__', '__main__'):
    TableApp().run()

这是.kv文件:

#:import Factory kivy.factory.Factory
Form:

<Form>:
    orientation: 'vertical'

    Widget1:    
    Widget2:

<Widget1>:
    Button:
        text: "Widget 1 Button" 
        on_press: root.click(self, 'arg')

<Widget2>:
    Button:
        text: 'Widget 2 Button'

<Widget3>:
    Button:
        text: 'Widget 3 Button'

在表格I中,检查Widgets1和2是该类的孩子:

print 'these are the children of the Form class:', self.children

我得到了:

these are the children of the Form class: [<__main__.Widget2 object at 0x7fe5833317c0>, <__main__.Widget1 object at 0x7fe5833316e0>]

因此,当我尝试删除现有的孩子并添加一个新孩子时,我得到了:

TypeError: descriptor 'unbind' of 'kivy._event.EventDispatcher' object needs an argument

有人可以帮忙吗?谢谢。

2 个答案:

答案 0 :(得分:3)

大多数问题都是因为您创建了新的小部件而不是使用现有的小部件。

这是一个工作示例(查看注释):

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.factory import Factory #no need for this


class Form(BoxLayout):
    def click(self, instance, arg):
        print ('this is the Form class')
        print ('this is my arg ... ', arg)
        print ('this is the button pressed ... ', instance)
        print ('these are the children of the Form class:', self.children)
        #notice! here we use self, not Form() which will make a new Form instance
        self.remove_widget(self.children[0]) #should be Widget2
        self.add_widget(Widget3()) #Here we really want a new widget

class Widget1(BoxLayout):

    def click(self, instance, arg):
        print ('this is the Widget 1')
        print ('this is my arg ... ', arg)
        print ('this is my instance', instance, '\n')
        self.parent.click(instance,arg) #changed to use the existing From instance instead of tring to create a new one

class Widget2(BoxLayout):
    pass

class Widget3(BoxLayout):
    pass



class TableApp(App):


    def on_pause(self): return True

    def on_resume(self): pass

if __name__ in ('__android__', '__main__'):
    TableApp().run()

答案 1 :(得分:1)

您在print日志中看到子项的唯一原因是因为它们在kv lang中使用。这根本不起作用:

Form().remove_widget(Widget2)
Form().add_widget(Widget3)

让我们做一点绘画:

App                   |  "Form()" called:              # this is how Form (A) gets created
 |                    |     |
 |- Form (A)          |  new Form instance created     # this is the click event beginning
     |                |       |                         
     |- Widget1       |       |- remove_widget of -> Form()                     
     |     |          |                                |                        
     |     |- Button  |    new Form instance created  -|                        
     |                |        |                       |
     |- Widget2       |        |- remove_widget(class) |
           |          |             ^                  |
           |- Button  |             |- crash           |
                      |                                |
                      |    new Form instance created  -|

左边部分是kv文件的作用,右边部分是你/ python代码。我们拨打已经可用的{kv} Form表单A

  1. 表单A是表单类的实例,并具有click方法
  2. 您点击A实例的图形表示,即BoxLayout区域
  3. print没有任何问题,所以它只是通过,instance可能是Button个实例(你应该使用{{ 1}},阅读(un)packing arguments
  4. 在表单*args中,A行会被注意到,这是我绘图的右侧
    • 每个Form()将创建一个类Form()的新实例(与表单A无关)(这些括号)
    • 创建并初始化新实例时,它会使用参数Form调用remove_widget
      • 没有实例,那是,因此它不能是&#34; Widget2&#34;
      • 即使你使用正确的东西 - 一个实例,它仍然会崩溃,因为那里有&#39;在新创建的unbind实例中没有这样的子节点。这些孩子的格式为Form