如何将多列放入奇异的RecycleView中?

时间:2019-04-15 15:06:41

标签: python kivy kivy-language

我想将(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列中看到中的数据,但是由于某些原因它们仍然为空。

2 个答案:

答案 0 :(得分:0)

该字段为空,因为未填充data

解决方案

  • 删除class Tabelle()中的所有编码
  • pass添加到class Tabelle()
  • 将以下内容添加到__init__()中的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(基本上是一个列表)来生成视图   的字典,并使用这些字典生成视图类的实例   根据需要。

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()

输出

Result

答案 1 :(得分:0)

基于之前的解决方案,这里的代码更容易解​​释。此外,其中一列是复选框。

结果: enter image description here

Python 文件:

cmake_minimum_required (VERSION 3.8)

set(PROJECT GUI_Engine)

add_executable (${PROJECT} "./src/driver/main.cpp")

set(HEADER_FILES ./src/include)
set(DEC_FILES ./src/lib)
set(PKGPATH C:/dev/vcpkg/packages)

add_library(engine ${DEC_FILES}/engine.cpp ${HEADER_FILES}/engine.hpp)

list(APPEND CMAKE_PREFIX_PATH ${PKGPATH}/sdl2_x64-windows)
find_package(SDL2 CONFIG REQUIRED)
target_link_libraries(${PROJECT} PRIVATE engine SDL2::SDL2main)
target_link_libraries(engine PRIVATE SDL2::SDL2)

list(APPEND CMAKE_PREFIX_PATH ${PKGPATH}/glew_x64-windows)
find_package(GLEW REQUIRED)
target_link_libraries(engine PRIVATE GLEW::GLEW)

KV 文件:

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()

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

结果: enter image description here

Python 文件:

<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'

KV 文件:

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()