Kivy RecycleView作为ListView的替代品?它是如何工作的?

时间:2017-09-19 09:31:46

标签: python-3.x kivy kivy-language

我应该断言我还是Kivy的新手。 我尝试寻找类似的问题,但它们已经过时或不清楚。

我正在寻找能够显示元素列表的元素,其中一个用户可以选择一个与其他小部件交互的元素(按钮等)。 我偶然发现了documentation page on ListView,但它明确指出不推荐使用ListView,而是必须使用RecycleView

现在问题是文档似乎不太清楚(至少对我来说)如何使用RecycleView。它肯定比其他小部件更复杂,我似乎无法弄明白。

将其分解为更容易理解的问题: 1.如何定义充当项目列表的RecycleView? 2.我如何提供物品? 3.我如何与它进行交互,特别是关于一次只能选择一个项目,检测何时选择某些内容并自动在事件中选择某些内容?

哦顺便说一句,我更喜欢尽可能使用kv语言。

我非常感谢找到或理解文档资源的一些帮助,这些资源可以让我更频繁地理解这些资源以供将来使用。我真的希望有一个关于这些复杂功能的教程,但是如果它存在的话,很难找到它。

2 个答案:

答案 0 :(得分:3)

下面的示例说明了如何使用Recycleview显示按钮列表,当每个按钮被选中时,它会显示一个弹出窗口。

实施例

main.py

from kivy.app import App
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.popup import Popup
from kivy.properties import ListProperty, StringProperty, ObjectProperty


class MessageBox(Popup):

    def popup_dismiss(self):
        self.dismiss()


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior, RecycleBoxLayout):
    """ Adds selection and focus behaviour to the view. """
    selected_value = StringProperty('')
    btn_info = ListProperty(['Button 0 Text', 'Button 1 Text', 'Button 2 Text'])


class SelectableButton(RecycleDataViewBehavior, Button):
    """ Add selection support to the Label """
    index = None

    def refresh_view_attrs(self, rv, index, data):
        """ Catch and handle the view changes """
        self.index = index
        return super(SelectableButton, self).refresh_view_attrs(rv, index, data)

    def on_press(self):
        self.parent.selected_value = 'Selected: {}'.format(self.parent.btn_info[int(self.id)])

    def on_release(self):
        MessageBox().open()


class RV(RecycleView):
    rv_layout = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'text': "Button " + str(x), 'id': str(x)} for x in range(3)]


class TestApp(App):
    title = "RecycleView Button Popup Demo"

    def build(self):
        return RV()


if __name__ == "__main__":
    TestApp().run()

test.kv

#:kivy 1.10.0

<MessageBox>:
    title: 'Popup Message Box'
    size_hint: None, None
    size: 400, 400

    BoxLayout:
        orientation: 'vertical'
        Label:
            text: app.root.rv_layout.selected_value
        Button:
            size_hint: 1, 0.2
            text: 'OK'
            on_press:
                root.dismiss()

<SelectableButton>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (0.0, 0.9, 0.1, 0.3)
        Rectangle:
            pos: self.pos
            size: self.size

<RV>:
    rv_layout: layout
    viewclass: 'SelectableButton'
    SelectableRecycleBoxLayout:
        id: layout
        default_size: None, dp(56)
        default_size_hint: 0.1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: "vertical"

输出

Recycleview of buttons with popups

答案 1 :(得分:1)

我做了一个更简单的例子。在我的示例中,可以更改每行的布局,包括使用kv语言的RecycleViewRow类中的Widgets。 我已经在每行中放置了一个Label和一个Button作为示例。 我希望这会有所帮助。

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview import RecycleView
from kivy.uix.popup import Popup

Builder.load_string('''
#:kivy 1.10.0
#: import Popup kivy.uix.popup

<MessageBox>:
    title: 'Popup Message Box'
    size_hint: None, None
    size: 400, 400

    BoxLayout:
        orientation: 'vertical'
        Label:
            text: root.message
        Button:
            size_hint: 1, 0.2
            text: 'OK'
            on_press: root.dismiss()

<RecycleViewRow>:
    orientation: 'horizontal'
    Label:
        text: root.text
    Button:
        text: 'Show'
        on_press: app.root.message_box(root.text)

<MainScreen>:
    viewclass: 'RecycleViewRow'
    RecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'                    
                    ''')

class MessageBox(Popup):
    message = StringProperty()

class RecycleViewRow(BoxLayout):
    text = StringProperty()   

class MainScreen(RecycleView):    
    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)
        self.data = [{'text': "Button " + str(x), 'id': str(x)} for x in range(3)]

    def message_box(self, message):
        p = MessageBox()
        p.message = message
        p.open() 
        print('test press: ', message)

class TestApp(App):
    title = "RecycleView Direct Test"

    def build(self):
        return MainScreen()

if __name__ == "__main__":
    TestApp().run()