[Kivy] RecycleViewのデータにフィルタをかける

RecycleViewのデータへのフィルタについて

 RecycleViewに表示する全データの内特定の条件を満たすデータのみを抽出して表示することは、Pythonのリストと同じようにRecycleViewのデータ(辞書データをリストにしたもの)にフィルタ処理をおこなうとできます。RecyclViewのデータにフィルタ処理する場合、①出力結果にフィルタ処理後のリストが得られる「ifで条件分岐したリスト内包表記」が便利であり、②元データを残しておくために元データは別のリストに保存しておき、そのリストにフィルタ処理をおこなった結果をRecycleViewに表示するのが良いと思います。

 今回は、RecycleViewのデータにフィルタ処理のおこなう方法について紹介します。

RecycleViewのデータへのフィルタ処理

 RecycleViewのデータ(data)にフィルタ処理をおこなう場合、フィルタの解除やフィルタの変更をおこなうことを考慮すると、元のデータは残しておく必要があります。このため、RecyclViewのデータにフィルタ処理をおこなう場合は元のデータをリストに保存しておき、そのリストにフィルタをかけたものをRecyclViewのデータに渡すのが良いと思います。また、リストに対するフィルタ処理は、フィルタを掛けた結果がそのままリストとして出力される「ifで条件分岐したリスト内包表記」を使用するのが便利です。

 以下の例では、self.data(元のデータ)の各辞書データの’text1’の値がtextと同じデータを抜き出して、リストに追加しています。このようにすれば、元のデータはself.dataに残りますので、フィルタの変更や解除をおこなうことが可能です。

def on_button_press(self, text):
    self.ids.rv.data = \
        [x for x in self.data if x['text1'] == text]

サンプルプログラム

 以下のサンプルプログラムは、実行すると左図のようなRecycleViewとその下に3つのボタンが配置された画面が表示されます。3つのボタンにはRecycleViewの左列と同じ名前が付いています。それぞれのボタンを押すとRecycleViewの左列が押したボタンと同じデータのみが表示されるようになります。

# -*- coding: utf-8 -*-

import kivy

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.config import Config
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty

kivy.require('2.2.0')

Config.set('graphics', 'width', '250')
Config.set('graphics', 'height', '500')

Builder.load_string('''

<MainD>
    BoxLayout:
        orientation: 'vertical'
        size: root.size
        padding: 20

        RecycleView:
            id: rv
            viewclass: 'RVBox'
            RecycleBoxLayout:
                size_hint_y: None
                height: self.minimum_height
                orientation: 'vertical'

        BoxLayout:
            size_hint_y: 0.2
            Button:
                text: 'data1'
                on_press: root.on_button_press('data1')

            Button:
                text: 'data2'
                on_press: root.on_button_press('data2')

            Button:
                text: 'data3'
                on_press: root.on_button_press('data3')

<RVBox@BoxLayout>:
    text1: ''
    text2: ''
    Label:
        text: root.text1
        size_hint_x: None
        width: 100
    Label:
        text: root.text2
        size_hint_x: None
        width: 100
''')


class MainD(Widget):

    def __init__(self, **kwargs):
        super(MainD, self).__init__(**kwargs)
        self.data = [
            {'text1': 'data1', 'text2': 'data1_1'},
            {'text1': 'data1', 'text2': 'data1_2'},
            {'text1': 'data2', 'text2': 'data2_1'},
            {'text1': 'data2', 'text2': 'data2_2'},
            {'text1': 'data2', 'text2': 'data2_3'},
            {'text1': 'data3', 'text2': 'data3_1'},
            {'text1': 'data3', 'text2': 'data3_2'},
            {'text1': 'data3', 'text2': 'data3_3'},
            {'text1': 'data2', 'text2': 'data2_3'}
            ]

        self.ids.rv.data = self.data

    def on_button_press(self, text):
        self.ids.rv.data = \
            [x for x in self.data if x['text1'] == text]


class MainDApp(App):
    def __init__(self, **kwargs):
        super(MainDApp, self).__init__(**kwargs)
        self.title = 'RecycleView Test1'

    def build(self):
        return MainD()


if __name__ == '__main__':
    app = MainDApp()
    app.run()
タイトルとURLをコピーしました