【问题标题】:Kivy Multiple Column RecyclerViewKivy 多列回收器视图
【发布时间】:2018-07-15 13:06:35
【问题描述】:

我只是在玩 Pythonkivy ,根据 kivy 官方文档,我已将我的字符串数据加载到 RecyclerView 中。但是我在将对象加载到列表中的多个列时遇到了麻烦,比如表单数据。例如,我想将姓名、姓氏和年龄设置为三列,标题标题逐行,我也尝试过RecyclerGridLayout 3 列,但无论逐行要求如何,它都可以只将姓名加载到网格中

<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 上工作

【问题讨论】:

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


【解决方案1】:

我也在寻找这个,但我找不到具体的例子,所以我提供了我的解决方案。正如 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()

【讨论】:

  • 注意:“SelectableLabel”用词不当。它不是一个标签,它是一个 GridLayout。该名称是其衍生示例的遗产。
  • 是的,你是对的。它可以被编辑为 SelectableGridItem 或类似的。
【解决方案2】:

不要使用Label 作为视图类,而是创建一个自定义类。这可能是一个有两个盒子的水平盒子布局。

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

【讨论】:

    【解决方案3】:

    我使用了来自@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()
    

    尝试一下,如果您还有任何问题,请告诉我。

    【讨论】:

      【解决方案4】:

      我想在表格中添加一个标题行;而且,我正在尝试以下方法:

      <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 的东西。 :-(

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-20
        • 2018-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多