当前位置: 首页 > 知识库问答 >
问题:

添加-删除kivy中的小部件

张丁雷
2023-03-14

我在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'

在类表单中,我检查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个答案

轩辕佑运
2023-03-14

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

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文件所做的,右边的部分是you/python代码。让我们调用已经可用的(通过kvForma表单a

  • Form A是Form类的一个实例,它有一个单击方法
  • 单击A实例的图形表示,即在BoxLayout的区域
  • 没有什么问题prints,所以它会通过只是OK,实例将可能是Button实例(你真的应该使用*args,阅读关于(un)包装参数)
  • 在formA中,Form()行被注意到,这是我画的右边
    • 每个Form()将创建一个新的实例(与formA无关)的类Form(那些括号)
    • 当一个新实例被创建和初始化时,它将调用remove_widget参数Widget2
      • 这不是实例,这是一个类,因此它不能是unbind
      • 即使你使用了正确的东西-实例,它仍然会崩溃,因为在新创建的Form实例中没有这样的子实例。孩子们在形式A

张权
2023-03-14

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

下面是一个工作示例(看看评论):

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()
 类似资料:
  • 我试图在屏幕中间构造一个窗口小部件。我没有使用pos_hint或size_hint,因为我将在以后更改小部件的位置,但是当我构建小部件时,它的大小和位置不正确。这是我的密码: 为什么小部件的大小不等于窗口大小的十分之一,为什么它的中心在窗口的右上角?

  • 我想问一下,我如何在我的应用程序中动态添加一些小部件,一个接一个,而不是一次添加完。这些小部件被添加到包含命令的for循环中,并由按钮触发。所以我想知道是否有办法在执行结束时逐渐显示输出,而不是一次显示完。起初,我试图在for循环中添加延迟,但恐怕这与每次构建输出的方式有关。 编辑:嗯,似乎我没有很好地理解和的用法,所以我对他们(或time.sleep)的尝试没有成功在所有。但显然,这是我问题的解

  • 我试着用Kivy模仿flappy birds,但目前我的处境很艰难。问题是我不知道如何在视图中创建多个小部件。 现在我的kv文件中有: 目前我能够制作单列,所以问题是如何制作才能有多列?

  • 我正在使用Kivy python库。 我定义了两个小部件。 当程序运行时,我运行第一个小部件。 当按下widgets按钮时,我希望它消失并被第二个widget替换。 这是两个小部件的. kv 我的主python文件运行应用程序,并返回第一个小部件 我的第一个小部件有一个回调。这就是问题代码所属的位置 这里的想法是有一个用户界面管理器。此管理器不像树那样运行UI,而是像列表和堆栈一样运行UI。该列表

  • 问题内容: 我正在使用Kivy做proyect,但复选框有问题。起初,我试图像python编码那样做程序(我知道它不是很干净,但是我理解得更多),并且我有了使用此编码的第一个屏幕: 例如,我想选择两个或三个选项,然后像选择类型一样保存到下一个屏幕。如果有人知道该怎么做并为下一个屏幕保存信息,那将对我有很大帮助,因为我拥有所有选项的下一个屏幕代码,但是我想在第一个屏幕中进行预选择,然后仅使用选择了。

  • 我在刷新小部件的BoxLayout时遇到了问题,方法是删除它们,然后根据列表“组”重新构建小部件。在EditDeviceGroups屏幕上,“创建”按钮应向列表中添加一个元素,并将用户转发到GroupTemplateScreen,确实如此。 当用户使用“后退”按钮返回到EditDeviceGroups屏幕时,会出现此问题。当时,我认为on_enter方法将刷新小部件以包含新元素,但列表中没有显示任