1

我试图访问 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()
4

2 回答 2

2

您似乎想更改提供给列表视图的数据,您不必为此更改整个 ListView。看这里https://github.com/kivy/kivy/issues/1321这提到了一种解决方法,直到 listview 的 data_changed 分支合并到 master 中。基本上只需将其添加到您的 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)

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

文档中的相关文档::

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
于 2013-09-14T19:52:17.553 回答
1

您可以只保留对列表视图(或您放入其中的任何其他内容)的引用,然后再对其进行修改,而不是乱用 tabbedpanel.content。

例如,在本例中,您将列表视图存储为 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
于 2013-09-10T09:44:27.883 回答