Kivy:点击第一个内容中的按钮,将第一个手风琴项目内容更改为另一个

时间:2014-04-19 09:00:09

标签: python accordion kivy

我是Kivy的新手,我的手风琴带有动态数量的物品。每个项目可以有两个不同的内容。您可以通过单击第一个内容中的按钮将第一个内容更改为另一个内容。这是一个简单的例子:

from kivy.lang import Builder
from kivy.base import runTouchApp

from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.accordion import Accordion, AccordionItem

Builder.load_string('''
<MyAccordion>:
    orientation: 'vertical'

<MyAccordionItem>:
    FirstContent:

<FirstContent@GridLayout>:
    cols: 1
    BoxLayout:
        ClickMeButton:
            text: 'Click me'
            on_press: self.change_content()

<SecondContent>:
    cols: 1
    GridLayout:
        rows: 1
        Label:
            text: 'You clicked!'
''')

class MyAccordionItem(AccordionItem):
    pass

class MyAccordion(Accordion):
    def __init__(self, **kwargs):
        super(MyAccordion, self).__init__(**kwargs)

        for i in xrange(5):
            accordionitem = MyAccordionItem(title=str(i))
            self.add_widget(accordionitem)

class SecondContent(GridLayout):
    pass

class ClickMeButton(Button):
    def change_content(self):

        # how to reference the accordion item
        # this button belongs to?

        '''
        accordionitem = None
        accordionitem.clear_widgets()
        accordionitem.add_widget(SecondContent())
        '''

runTouchApp(MyAccordion())

我遇到的问题是我不知道如何引用该按钮所属的手风琴项目。我试图链接父母,它到达FirstContent对象,但它的父亲似乎是一个盒子布局由于某种原因(为什么?)。好吧,链接父母不是最好的主意,因为如果内容结构级别发生变化,它很容易破坏。

我注意到Kivy 1.8.1会有一个walk()方法,但我想这会使用父母向上遍历树,所以这可能也不起作用?

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

更改change_button的代码,如下所示。这是一种引用您想要的方式。可能还有其他一些方法可以做到这一点,但希望这可以帮助你:)

我们是怎么做到的? 第一个父级是Class FirstContent中的按钮的框布局...您在ClickMeButton上方的kv代码中指定的BoxLayout

第二个父母,即父母以上是第一个内容

依旧......

class ClickMeButton(Button):
    def change_content(self):
        print "I am clicked . I am button "
        print self.parent.parent.parent.parent.parent.parent.title

        #1kivy.uix.boxlayout.BoxLayout object at 0x06ED9228 -- boxlayout in ClickMeButton
        #2<kivy.factory.FirstContent object at 0x06FCA1F0>   --Parent above
        #3<kivy.uix.boxlayout.BoxLayout object at 0x06F591B8> -- Parent of firstcontent class as a boxlayout
        #4<kivy.uix.stencilview.StencilView object at 0x06F3B0A0>
        #5<kivy.uix.boxlayout.BoxLayout object at 0x06FB7068>
        #6<__main__.MyAccordionItem object at 0x06ED8030>

答案 1 :(得分:0)

这是我为ClickMeButton类提出的解决方案:

class ClickMeButton(Button):

    def change_content(self):

        accordionitem = self.find_anchestor(self.parent, 'MyAccordionItem')
        accordionitem.remove_widget(accordionitem.ids['_first_content'])
        accordionitem.add_widget(SecondContent())

    def find_anchestor(self, widget, classname):

        if widget:
            if widget.__class__.__name__ == classname:
                return widget

            else:
                return self.find_anchestor(widget.parent, classname)

在kivy语言字符串中,我还需要在id: _first_content下面添加FirstContent:,以便为实例提供我可以引用的ID。

我创建了一个递归函数find_anchestor来搜索正确的父级。 Paarth batra告诉我,我最终可以通过父链接找到正确的安慰。但是当布局发生变化时,我不想手动添加或删除链中的父项,因此递归函数会一直运行直到找到正确的函数。给它一个小部件从头开始,小部件类的名称是你正在寻找的实例,它应该可以工作。

找到正确的父窗口小部件后,我需要删除第一个内容并添加第二个内容。由于第一个内容不是accordionitem小部件的直接子节点,因此我需要使用ids属性为其指定id和引用。

最后,我只是添加第二个内容。

我希望这有助于将来遇到类似问题的人。感谢帕特斯巴特拉为你的想法!

答案 2 :(得分:0)

只需给你的AccordionItem / s一个id,如果你想要折叠所有的AccordionItems,除了显示一个(active_accordion_item),在你的按钮中使用它:

on_release:active_accordion.collapse = False

  • kivy会将所有其他Acc / Items变为True