【问题标题】:How to put multiple columns into a kivy RecycleView?如何将多列放入 kivy RecycleView?
【发布时间】:2019-04-15 15:06:40
【问题描述】:

我想将(csv-)表的数据放入 kivy recycleview。

如果我将固定文本分配给 kv 中的标签,我设法在一行中插入多个列,但我无法用字典列表中的数据填充标签。到目前为止,这是我用来测试概念的代码:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.boxlayout import BoxLayout
import csv

items = [{'SP1': 'Artikelnummer', 'SP2': 'Name', 'SP3': 'Groesse'},
    {'SP1': '510001', 'SP2': 'Big Pump', 'SP3': '1.50 L'},
    {'SP1': '523001', 'SP2': 'Leonie Still', 'SP3': '1.50 L'},
    {'SP1': '641301', 'SP2': 'Cola Mix', 'SP3': '1.50 L'}
]

class Tabelle(BoxLayout):
    def __init__(self, **kwargs):
        super(Tabelle, self).__init__(**kwargs)

    def insert_SP(self, data):
        for i in data:
            self.spalte1_SP = i['SP1']
            #print(self.spalte1_SP)
            self.spalte2_SP = i['SP2']
            self.spalte3_SP = i['SP3']

Builder.load_string('''
<Tabelle>:
    orientation: 'horizontal'
    spalte1_SP: 'spalte1'
    spalte2_SP: 'spalte2'
    spalte3_SP: 'spalte3'
    Label:
        id: Spalte1
        text: root.spalte1_SP
    Label:
        id: Spalte2
        text: root.spalte2_SP
    Label:
        id: Spalte3
        text: root.spalte3_SP

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

class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        #self.data = []
        x = Tabelle()
        x.insert_SP(items)

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

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

我希望在 3 列中看到来自 items 的数据,但由于某种原因它们保持为空。

【问题讨论】:

    标签: python kivy kivy-language


    【解决方案1】:

    它是空的,因为data 没有被填充。

    解决方案

    • 删除class Tabelle()中的所有编码
    • pass 添加到class Tabelle()
    • 将以下内容添加到构造函数中,__init__() of class RV()

    片段

    self.data = [{'spalte1_SP': str(x['SP1']), 'spalte2_SP': str(x['SP2']), 'spalte3_SP': str(x['SP3'])} for x in items]
    

    Kivy RecycleView » data

    视图是通过处理data 生成的,本质上是一个列表 dicts,并使用这些dicts来生成viewclass的实例 根据需要。

    data
    

    当前视图适配器使用的数据。这是字典列表 其键映射到视图类的相应属性名称。

    data 是一个 AliasProperty,它获取和设置用于生成的数据 意见。

    示例

    main.py

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.recycleview import RecycleView
    from kivy.uix.boxlayout import BoxLayout
    
    items = [{'SP1': 'Artikelnummer', 'SP2': 'Name', 'SP3': 'Groesse'},
             {'SP1': '510001', 'SP2': 'Big Pump', 'SP3': '1.50 L'},
             {'SP1': '523001', 'SP2': 'Leonie Still', 'SP3': '1.50 L'},
             {'SP1': '641301', 'SP2': 'Cola Mix', 'SP3': '1.50 L'}
             ]
    
    
    class Tabelle(BoxLayout):
        pass
    
    
    Builder.load_string('''
    <Tabelle>:
        orientation: 'horizontal'
        spalte1_SP: 'spalte1'
        spalte2_SP: 'spalte2'
        spalte3_SP: 'spalte3'
        Label:
            id: SP1
            text: root.spalte1_SP
        Label:
            id: SP2
            text: root.spalte2_SP
        Label:
            id: SP3
            text: root.spalte3_SP
    
    <RV>:
        viewclass: 'Tabelle'
        RecycleBoxLayout:
            default_size: None, dp(20)
            default_size_hint: 1, None
            size_hint_y: None
            height: self.minimum_height
            orientation: 'vertical'
    ''')
    
    
    class RV(RecycleView):
        def __init__(self, **kwargs):
            super(RV, self).__init__(**kwargs)
            self.data = [{'spalte1_SP': str(x['SP1']), 'spalte2_SP': str(x['SP2']), 'spalte3_SP': str(x['SP3'])} for x in items]
    
    
    class TestApp(App):
        def build(self):
            return RV()
    
    
    if __name__ == '__main__':
        TestApp().run()
    

    输出

    【讨论】:

    • 我无语了。在坐了一整天之后,看到解决方案实际上看起来多么简单......你无法相信这对我有多大帮助!谢谢!
    • 不客气!另一种解决方案是使用viewclass: 'Label'RecycleGridLayout:cols: 3self.data = [{'text': val} for row in items for val in row.values()]
    • 谢谢,当我想添加更多列时看起来更通用。一定会测试出来的。
    【解决方案2】:

    基于前面的解决方案,这里有一段代码,它的解释要容易得多。此外,其中一列是复选框。

    结果:

    Python 文件:

    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.gridlayout import GridLayout
    
    # data
    items = [{'number': '510001', 'name': 'Big Pump', 'size': '1.50 L', 'in_stock': True},
             {'number': '523001', 'name': 'Leonie Still', 'size': '1.60 L', 'in_stock': False},
             {'number': '641301', 'name': 'Apple Mix', 'size': '1.30 L', 'in_stock': True},
             {'number': '681301', 'name': 'Orange Mix', 'size': '1.40 L', 'in_stock': True}
            ]
    
    
    class MultiFieldLine(BoxLayout):
        # class layout defined in kv file
        pass
    
    
    class AppGUI(GridLayout):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.rv.data = [{'label_1': str(x['number']), 'label_2': str(x['name']), 'label_3': str(x['size']), 'checkbox_1': x['in_stock']} for x in items]
    
    
    class ExploreRecycleViewMultipleFieldApp(App):
        def build(self):
            return AppGUI()
    
    
    if __name__ == '__main__':
        ExploreRecycleViewMultipleFieldApp().run()
    

    KV 文件:

    <MultiFieldLine>:
        orientation: 'horizontal'
        label_1: ''
        label_2: ''
        label_3: ''
        checkbox_1: False
        Label:
            text: root.label_1
        Label:
            text: root.label_2
        Label:
            text: root.label_3
        CheckBox:
            active: root.checkbox_1
    <AppGUI>: # inherit from GridLayout
        rv: rv_id
        cols:  1
        rows: 2
        GridLayout: # col titles
            cols: 4
            rows: 1
            size_hint_y: 0.04
            Label:
                text: 'Number'
            Label:
                text: 'Name'
            Label:
                text: 'Size'
            Label
                text: 'In stock'
        GridLayout: # data
            cols: 1
            rows: 1
            size_hint_y: 0.96
            RecycleView:
                id: rv_id
                viewclass: 'MultiFieldLine'
                RecycleBoxLayout:
                    default_size: None, dp(20)
                    default_size_hint: 1, None
                    size_hint_y: None
                    height: self.minimum_height
                    orientation: 'vertical'
    

    下面的版本增加了行选择以及名称列的更大标签宽度以及每次选择一行时调用的 gui 类中的方法。:

    结果:

    Python 文件:

    from kivy.app import App
    from kivy.properties import BooleanProperty
    from kivy.uix.behaviors import FocusBehavior
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.gridlayout import GridLayout
    
    # data
    from kivy.uix.recycleboxlayout import RecycleBoxLayout
    from kivy.uix.recycleview.layout import LayoutSelectionBehavior
    from kivy.uix.recycleview.views import RecycleDataViewBehavior
    
    items = [{'number': '510001', 'name': 'Big Pump', 'size': '1.50 L', 'in_stock': True},
             {'number': '523001', 'name': 'Leonie Still very, very,very long, long name', 'size': '1.60 L', 'in_stock': False},
             {'number': '641301', 'name': 'Apple Mix', 'size': '1.30 L', 'in_stock': True},
             {'number': '681301', 'name': 'Orange Mix', 'size': '1.40 L', 'in_stock': True}
            ]
    
    
    class MultiFieldLine(RecycleDataViewBehavior, BoxLayout):
        ''' class layout defined in kv file '''
        index = None
        selected = BooleanProperty(False)
        selectable = BooleanProperty(True)
        
        def refresh_view_attrs(self, rv, index, data):
            ''' Catch and handle the view changes '''
            self.rv = rv
            self.appGUI = rv.appGUI
            self.index = index
            
            return super(MultiFieldLine, self).refresh_view_attrs(
                rv, index, data)
        
        def on_touch_down(self, touch):
            ''' Add selection on touch down '''
            if super(MultiFieldLine, 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):
            # instance variable used in .kv file to change the selected item
            # color !
            self.selected = is_selected
      
            if is_selected:
                self.appGUI.outputSelectedData(rv.data[index])
    
    
    class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                     RecycleBoxLayout):
        ''' Adds selection and focus behaviour to the view. '''
        
        # required to authorise unselecting a selected item
        touch_deselect_last = BooleanProperty(True)
    
    
    class AppGUI(GridLayout):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.rv.data = [{'label_1': str(x['number']), 'label_2': str(x['name']), 'label_3': str(x['size']), 'checkbox_1': x['in_stock']} for x in items]
    
        def outputSelectedData(self, data):
        # method called when a line is selected
            print(data)
    
    class ExploreRecycleViewMultipleFieldBoxLayoutApp(App):
        def build(self):
            return AppGUI()
    
    
    if __name__ == '__main__':
        ExploreRecycleViewMultipleFieldBoxLayoutApp().run()
    

    KV 文件:

    <MultiFieldLine>: # inherit from RecycleDataViewBehavior and BoxLayout
        orientation: 'horizontal'
        label_1: ''
        label_2: ''
        label_3: ''
        checkbox_1: False
        # add selection background
        canvas.before:
            Color:
                rgba: (1, 0, 0, 1) if self.selected else (.0, 0.9, .1, .3)
            Rectangle:
                pos: self.pos
                size: self.size
            Color:
                rgba: (0, 0.9, .1, .3)
        Label:
            size_hint_x: 0.1
            text: root.label_1
        Label:
            size_hint_x: 0.7
            text: root.label_2
        Label:
            size_hint_x: 0.1
            text: root.label_3
        CheckBox:
            size_hint_x: 0.1
            active: root.checkbox_1
    <AppGUI>: # inherit from GridLayout
        rv: rv_id
        cols:  1
        rows: 2
        GridLayout: # col titles
            cols: 4
            rows: 1
            size_hint_y: 0.04
            Label:
                size_hint_x: 0.1
                text: 'Number'
            Label:
                size_hint_x: 0.7
                text: 'Name'
            Label:
                size_hint_x: 0.1
                text: 'Size'
            Label
                size_hint_x: 0.1
                text: 'In stock'
        GridLayout: # data
            cols: 1
            rows: 1
            size_hint_y: 0.96
            RecycleView:
                id: rv_id
                appGUI: root
                viewclass: 'MultiFieldLine'
                SelectableRecycleBoxLayout:
                    default_size: None, dp(20)
                    default_size_hint: 1, None
                    size_hint_y: None
                    height: self.minimum_height
                    orientation: 'vertical'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多