从Kivy中的按钮更改选项卡的内容

时间:2013-09-10 07:38:30

标签: python tabs kivy

我尝试访问TabbedPanel.content.children [0]并删除子项并重新创建一个新子项,但它不起作用。需要注意的是TabbedPanel.content是一个TabbedPanelContent而不是ListView(在我的例子中)。

我想要做的是编辑listView的内容。该应用程序创建一个生成数据的按钮和两个选项卡,其中第一个选项卡创建数据的列表视图。如果再次按下按钮,它将删除以前的ListView并插入新的ListView。

如何更新标签的内容?代码:

#test tabs

import kivy
kivy.require('1.0.6') # replace with your current kivy version !

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelHeader
from kivy.properties import ListProperty
from kivy.properties import DictProperty
from kivy.uix.listview import ListView, ListItemButton
from kivy.adapters.dictadapter import DictAdapter
from kivy.adapters.models import SelectableDataItem
from kivy.uix.selectableview import SelectableView
from kivy.uix.listview import ListView, ListItemButton
from kivy.factory import Factory
from kivy.lang import Builder

import random

#templates kv for SelectableView+BoxLayout called CustomListItem
Builder.load_string('''
[CustomListItem@SelectableView+BoxLayout]:
    size_hint_y: ctx.size_hint_y
    height: ctx.height
    ListItemButton:
        text: ctx.text
        is_selected: ctx.is_selected
''')

class testTabs(BoxLayout):
    data = ListProperty([1,2,3,4,5])

    def __init__(self, *args, **kwargs):
        super(testTabs, self).__init__(**kwargs)
        self.listViewDict = {}
        #layout = GridLayout(rows = 2)
        self.layout = BoxLayout(orientation = "vertical")
        #buttonLayout = GridLayout(cols = 4)
        dataButton = Button(text = "press to load random data to tab 1")
        dataButton.bind(on_release = self.randData)
        self.layout.add_widget(dataButton)

        #create list
        list_item_args_converter = \
                lambda row_index, rec: {'text': rec['text'],
                                        'is_selected': rec['is_selected'],
                                        'size_hint_y': None,
                                        'height': 35}

        entry_dict = \
        {str(i): {'text': str(self.data[i]), 'is_selected': False} \
            for i in xrange(len(self.data) ) }

        self.listViewDict = entry_dict

        sortedDateEntriesList = sorted(self.listViewDict)
        dict_adapter = DictAdapter(sorted_keys = sortedDateEntriesList,
                                   data = self.listViewDict,
                                   args_converter=list_item_args_converter,
                                   template = 'CustomListItem')

        self.list_view = ListView(adapter=dict_adapter)

        ### Create tabs ###
        self.tabbedPanel = TabbedPanel()
        self.tabbedPanel.default_tab_text = "data tab"
        self.tabbedPanel.tab_pos = "top_left"
        self.tabbedPanel.default_tab_content = self.list_view

        tabbedPanelHeader = TabbedPanelHeader(text = "tab 2")
        tabbedPanelHeader.content = Label(text = "Hello world")

        self.tabbedPanel.add_widget(tabbedPanelHeader)

        self.layout.add_widget(self.tabbedPanel)

        self.add_widget(self.layout)

        #self.tabbedPanel.content.bind(children = self.foo)

    def foo(self, *args):
        print "############################in foo args:"
        print args
        tabbedPanelHeader = args[0]
        print tabbedPanelHeader.children

    def printContent(self, object):
        print "object:" +str(object) +"'s content: " +str(object.content)

    def printChildren(self, object):
        for child in object.children:
            print "object:" +str(object) +"'s child: " +str(child)

    #create list view
    def randData(self, *args):
        print args
        self.tabbedPanel.content.children[0].remove_widget(self.list_view)
        print "content tabbedPanel children:"
        print self.tabbedPanel.content.children

        tempData = []
        numValues = random.randint(10,20)-1
        for i in xrange(numValues):
            tempData.append(random.randint(1,30))
        self.data = tempData

        list_item_args_converter = \
                lambda row_index, rec: {'text': rec['text'],
                                        'is_selected': rec['is_selected'],
                                        'size_hint_y': None,
                                        'height': 35}

        entry_dict = \
        {str(i): {'text': str(self.data[i]), 'is_selected': False} \
            for i in xrange(len(self.data) ) }

        self.listViewDict = entry_dict

        sortedDateEntriesList = sorted(self.listViewDict)
        dict_adapter = DictAdapter(sorted_keys = sortedDateEntriesList,
                                   data = self.listViewDict,
                                   args_converter=list_item_args_converter,
                                   template = 'CustomListItem')

        self.list_view = ListView(adapter=dict_adapter)
        self.tabbedPanel.content.children[0].add_widget(self.list_view)

    def on_data(self, *args):
        print "on_data func. Data created:"
        print args

class MyApp(App):

    def build(self):
        return testTabs()

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

2 个答案:

答案 0 :(得分:1)

您可以只保留对listview(或其他任何内容)的引用,并稍后修改它,而不是使用tabbedpanel.content。

例如,在此示例中,您将listview存储为self.list_view。这意味着您可以拥有一个创建新适配器的方法,然后只需替换旧适配器即可更新列表。您也可以通过相同的参考来修改原始适配器的data

一些(未经测试的)示例代码类似于:

def my_update_method(self, *args):

    new_dict_adapter = DictAdapter(data = whatever 
                                   # Obviously you have to make thi
                                   args_converter = list_item_args_converter 
                                   # You have to make this too, not included in
                                   # the example
                                   )

    self.list_view.adapter = new_dict_adapter

答案 1 :(得分:1)

您似乎想要更改给予listview的数据,您不必为此更改整个ListView。看这里https://github.com/kivy/kivy/issues/1321这提到了一个解决方法,直到listview的data_changed分支在master中合并。 Eessentially只是将它添加到您的kv ::

<ListView>:
    on_adapter: self.adapter.bind_triggers_to_view(self._trigger_reset_populate)

之后只需更新数据即可在列表视图中显示您的更改。

对于TabbedPanel的问题,您需要做的就是::

self.tabbedPanel.clear_widgets()
self.tabbedPanel.add_widget(self.list_view)

将小部件添加到选项卡式面板时,它实际上会将其添加到内容区域。类似地,clear_widgets()清除内容区域。

您也可以::

self.tabbedPanel.default_tab.content = self.list_view
self.tabbedPanel.switch_to(self.tabbedPanel.default_tab)

这更好,因为链接内容已更新,因此每次更改选项卡时都会显示相应的更改内容。

docs ::

中的相关文档
Tabs and content can be removed in several ways:

    tp.remove_widget(Widget/TabbedPanelHeader)
or
    tp.clear_widgets() # to clear all the widgets in the content area
or
    tp.clear_tabs() # to remove the TabbedPanelHeaders

Warning

To access the children of the tabbed panel, use content.children:

    tp.content.children

To access the list of tabs:

tp.tab_list