Kivy:在kv中将回调绑定到SimpleListAdapter

时间:2014-06-19 00:35:01

标签: python kivy

我尝试做一些与Kivy Listview示例非常类似的事情 - 我使用Builder和kv创建一个ListView并用文本文件中的行填充它。我的问题是我无法弄清楚如何绑定回调,因此我可以将所选行的文本移到列表框中。我的代码:

from kivy.uix.listview import ListView, ListItemButton
from kivy.uix.gridlayout import GridLayout
from kivy.uix.modalview import ModalView
from kivy.uix.textinput import TextInput
from kivy.lang import Builder


Builder.load_string("""
#:import label kivy.uix.label
#:import sla kivy.adapters.simplelistadapter


<ListViewModal>:
    size_hint: None, None
    size: 400, 400
    ListView:
        id: listview_modal
        #on_selection_change: callback # <==== attempt #1
        size_hint: .8, .8
        adapter:
            sla.SimpleListAdapter(
            data=[s.strip() for s in open('/Users/zen/Dropbox/todo/todo.txt').readlines()],
            cls=label.Label,
            selection_mode='single',
            allow_empty_selection=True)
            #on_selection_change: callback # <===== attempt #2
""")

class ListViewModal(ModalView):
    def __init__(self, **kwargs):
        super(ListViewModal, self).__init__(**kwargs)

class MainView(GridLayout):
    '''Implementation of a simple list view that reads data from a file.
    '''

    def __init__(self, **kwargs):
        kwargs['cols'] = 2
        super(MainView, self).__init__(**kwargs)

        self.listview_modal = ListViewModal()
        self.add_widget(self.listview_modal)

        text_input = TextInput()
        self.add_widget(text_input)

    def callback(self, adapter):
        self.text_input.text = adapter.selection.text

if __name__ == '__main__':
    from kivy.base import runTouchApp
    runTouchApp(MainView(width=800))

我还尝试过添加ID和属性的各种组合,以便能够访问MainView类中的适配器,但都无济于事。

任何建议都将不胜感激!

1 个答案:

答案 0 :(得分:0)

第一个问题是你正在使用SimpleListAdapter - 它很简单&#39;因为它不支持选择。请改用常规ListAdapter。您还需要使用ListItemButton来支持选择。 on_selection_change事件必须绑定Python,而不是kv,否则它不会起作用。最后,您还遇到了text_input窗口小部件的几个问题,并尝试从text获取adapter.selection,这是一个列表而不是窗口小部件。

我已更新您的代码并使用评论注释我的更改。

Builder.load_string("""
#:import ListItemButton kivy.uix.listview.ListItemButton
#:import la kivy.adapters.listadapter


<ListViewModal>:
    size_hint: None, None
    size: 400, 400
    ListView:
        id: listview_modal
        size_hint: .8, .8
        adapter:
            la.ListAdapter(
            data=[s.strip() for s in open('/Users/zen/Dropbox/todo/todo.txt').readlines()],
            cls=ListItemButton,  ### use ListItemButton instead of Label
            selection_mode='single',
            allow_empty_selection=True)
""")

class ListViewModal(ModalView):
    def __init__(self, **kwargs):
        super(ListViewModal, self).__init__(**kwargs)
        ### Bind to `on_selection_change` here in `__init__`
        self.ids['listview_modal'].adapter.bind(on_selection_change=self.callback)

    ### in `__init__`, we don't have a parent yet, so we proxy the callback
    def callback(self, adapter):
        return self.parent.callback(adapter)

class MainView(GridLayout):
    '''Implementation of a simple list view that reads data from a file.
    '''

    def __init__(self, **kwargs):
        kwargs['cols'] = 2
        super(MainView, self).__init__(**kwargs)

        self.listview_modal = ListViewModal()
        self.add_widget(self.listview_modal)

        self.text_input = TextInput()  ### use `self.text_input` instead of `text_input`
        self.add_widget(self.text_input)

    def callback(self, adapter):
        self.text_input.text = adapter.selection[0].text  ### get `text` from the first selected item