Kivy多柱RecyclerView

时间:2018-07-15 13:06:35

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

我只是在玩Pythonkivy,根据kivy官方文档,我已经将String数据加载到RecyclerView中。但是我在将对象像表单数据一样加载到列表中的多个列时遇到了麻烦。例如,我想将姓名,姓氏和年龄分成三列,标题标题逐行显示,我也尝试过RecyclerGridLayout的三列标题,但是无论行与行的要求如何,它都只能将名称加载到网格中

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

将感谢任何提示或示例代码,以了解RecyclerView如何在kivy上工作

4 个答案:

答案 0 :(得分:2)

我也在寻找这个,但是找不到具体的例子,所以我提供了解决方案。正如el3ien所说,您将需要创建一个自定义类,该类将代表可选标签的每一行。

<SelectableLabel>:
# Draw a background to indicate selection
canvas.before:
    Color:
        rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
    Rectangle:
        pos: self.pos
        size: self.size
label1_text: 'label 1 text'  # I have included two methods of accessing the labels
label2_text: 'label 2 text'  # This is method 1
label3_text: 'label 3 text'
pos: self.pos
size: self.size
Label:
    id: id_label1  # method 2 uses the label id
    text: root.label1_text
Label:
    id: id_label2
    text: root.label2_text
Label:
    id: id_label3
    text: root.label3_text

在将数据应用到RV中时,您需要重组字典以反映标签布局

class RV(RecycleView):
def __init__(self, **kwargs):
    super(RV, self).__init__(**kwargs)
    paired_iter = zip(items_1, items_2)  # items_1 and items_2 are defined elsewhere
    self.data = []
    for i1, i2 in paired_iter:
        d = {'label2': {'text': i1}, 'label3': {'text': i2}}
        self.data.append(d)

最后,在refresh_view_attrs中,将指定绑定到每个标签的.label_text,或者可以使用标签ID。

def refresh_view_attrs(self, rv, index, data):
    ''' Catch and handle the view changes '''
    self.index = index
    self.label1_text = str(index)
    self.label2_text = data['label2']['text']
    self.ids['id_label3'].text = data['label3']['text']  # As an alternate method of assignment
    return super(SelectableLabel, self).refresh_view_attrs(
        rv, index, data)

完整代码如下:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior

Builder.load_string('''
<SelectableLabel>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
        Rectangle:
            pos: self.pos
            size: self.size
    label1_text: 'label 1 text'
    label2_text: 'label 2 text'
    label3_text: 'label 3 text'
    pos: self.pos
    size: self.size
    Label:
        id: id_label1
        text: root.label1_text
    Label:
        id: id_label2
        text: root.label2_text
    Label:
        id: id_label3
        text: root.label3_text

<RV>:
    viewclass: 'SelectableLabel'
    SelectableRecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
        multiselect: True
        touch_multiselect: True
''')


items_1 = {'apple', 'banana', 'pear', 'pineapple'}
items_2 = {'dog', 'cat', 'rat', 'bat'}


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                 RecycleBoxLayout):
    ''' Adds selection and focus behaviour to the view. '''


class SelectableLabel(RecycleDataViewBehavior, GridLayout):
    ''' Add selection support to the Label '''
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)
    cols = 3

    def refresh_view_attrs(self, rv, index, data):
        ''' Catch and handle the view changes '''
        self.index = index
        self.label1_text = str(index)
        self.label2_text = data['label2']['text']
        self.ids['id_label3'].text = data['label3']['text']  # As an alternate method of assignment
        return super(SelectableLabel, self).refresh_view_attrs(
            rv, index, data)

    def on_touch_down(self, touch):
        ''' Add selection on touch down '''
        if super(SelectableLabel, self).on_touch_down(touch):
            return True
        if self.collide_point(*touch.pos) and self.selectable:
            return self.parent.select_with_touch(self.index, touch)

    def apply_selection(self, rv, index, is_selected):
        ''' Respond to the selection of items in the view. '''
        self.selected = is_selected
        if is_selected:
            print("selection changed to {0}".format(rv.data[index]))
        else:
            print("selection removed for {0}".format(rv.data[index]))


class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        paired_iter = zip(items_1, items_2)
        self.data = []
        for i1, i2 in paired_iter:
            d = {'label2': {'text': i1}, 'label3': {'text': i2}}
            self.data.append(d)
        # can also be performed in a complicated one liner for those who like it tricky
        # self.data = [{'label2': {'text': i1}, 'label3': {'text': i2}} for i1, i2 in zip(items_1, items_2)]


class TestApp(App):
    def build(self):
        return RV()

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

答案 1 :(得分:2)

我使用了@ el3ien的上述想法。我的代码在下面。

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
Builder.load_string('''
<RV>:
    viewclass: 'myView'
    RecycleBoxLayout:
        default_size: None, dp(200)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'


<myView@BoxLayout>:
    BoxLayout:
        orientation: 'horizontal'


        BoxLayout:
            orientation: 'vertical'
            on_release:

            Button:
                size_hint: (1,1)
                background_normal: 'C:/Users/Arsalan/Desktop/dummyImage2.jpg'
                background_down: 'C:/Users/Arsalan/Desktop/dummyImage1.png'
                text: 
                text_size: self.size
                halign: 
                valign: 'middle'

            Label:
                size_hint: (1,0.3)
                text: 'Product summary'
                text_size: self.size 
                halign:
                valign: 'middle'
                canvas.before:
                    Color:
                        rgba: (0.6, 0.7, 0.4, 1)
                    Rectangle:
                        size: self.size
                        pos: self.pos
            BoxLayout:
                size_hint :(1,0.01)

            Label:
                size_hint: (1,0.3)
                text: 'Rs 600'
                text_size: self.size 
                halign:
                valign: 'middle'




        BoxLayout:
            orientation: 'vertical'
            size_hint: (0.001,1)




        BoxLayout:
            orientation: 'vertical'
            on_release:

            Button:
                size_hint: (1,1)
                background_normal: 'C:/Users/Arsalan/Desktop/dummyImage2.jpg'
                background_down: 'C:/Users/Arsalan/Desktop/dummyImage1.png'
                text: 
                text_size: self.size
                halign: 
                valign: 'middle'

            Label:
                size_hint: (1,0.3)
                text: 'Product summary'
                text_size: self.size 
                halign:
                valign: 'middle'
                canvas.before:
                    Color:
                        rgba: (0.6, 0.7, 0.4, 1)
                    Rectangle:
                        size: self.size
                        pos: self.pos
            BoxLayout:
                size_hint :(1,0.01)

            Label:
                size_hint: (1,0.3)
                text: 'Rs 600'
                text_size: self.size 
                halign:
                valign: 'middle'




''')
class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'text': str(x)} for x in range(100)]
class TestApp(App):
    def build(self):
        return RV()
if __name__ == '__main__':
    TestApp().run()

尝试一下,让我知道您是否还有任何疑问。

答案 2 :(得分:1)

创建自定义类,而不是使用Label作为视图类。那可能是带有两个框的水平框布局。

<CustomClass@BoxLayout>:
    orientation: "horizontal"
    Label:
    Label:

答案 3 :(得分:0)

我想在表中添加标题行;而且,我正在尝试以下操作:

<RV>:
    BoxLayout:
        orientation: "vertical"

        BoxLayout:
            orientation: 'horizontal'
            size_hint: 1, None
            size_hint_y: None
            height: 25
            Label:
                text: "Item"
            Label:
                text: "User ID"
            Label:
                text: "User Name"

        BoxLayout:
            RecycleView:
                id: review
                viewclass: 'SelectableLabel'
                SelectableRecycleBoxLayout:
                    default_size: None, dp(56)
                    default_size_hint: 1, None
                    size_hint_y: None
                    height: self.minimum_height
                    orientation: 'vertical'
                    multiselect: True
                    touch_multiselect: True

但是:SelectableRecycleBoxLayout然后更深入地进入层次结构,我不再得到表,只有标题...如何解决此问题?我仍然不太了解如何从python获取kv东西。 :-(