質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.63%

kivyで、recycleviewの行を削除したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 139

kintarock777

score 20

kivyで recycleviewのリストに削除ボタンを設定しました。
選択した行を削除したいです。
選択していない行は、削除ボタンを押しても削除されないようにしたいです。
SelectablLabelクラスの中に削除用のモジュールを作りたいです。
あと、行が選択されているか否かの判別も行いたいです。

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.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior

import japanize_kivy

Builder.load_string('''
<SelectableLabel>:
    canvas.before:
        Color:
            rgba: (.8, .8, .8, 1) if self.selected else (1, .8, .8, 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
    #    color: [0,0,0,1]
    #    font_size: 20

    Label:
        id: id_label2
        text: root.label2_text
        color: [0,0,0,1]
        font_size: 20
        size_hint_x: 4

    Label:
        id: id_label3
        text: root.label3_text
        color: [0,0,0,1]
        font_size: 20
        size_hint_x: 4
    Button:
        text: '削除'
        font_size: 20
        size_hint_x: 2
        on_press: detach_recycleview() #どのように当該の行と関連づけるか?

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

''')

items_1 = ['カツ丼','天丼','親子丼','玉子丼','オムライス','カツカレー']
items_2 = ['850','850','750','670','800','850']

class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                 RecycleBoxLayout):
    pass

class SelectableLabel(RecycleDataViewBehavior, GridLayout):

    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.label3_text = data['label3']['text']
        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 {}'.format(rv.data[index]))
        else:
            print('selection removed for {}'.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)

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

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

よろしくお願いいたします。

その後調べましたが、削除Buttonのon_pressにdetach_recycleview()を付けること
ぐらいしか思いつきませんでした。
今知りたいことは、

  1. detach_recycleview であっているかどうか?
  2. あっている場合、その削除Buttonと削除したい行をどのように関連づけるか?
  3. あと、kivyファイルの方に書き込んだ方がよいか、classの中にdefとして、
    書き込んだ方がよいかです。

知識がなさ過ぎて、質問の仕方もよくわからなくてすみません。

なんとかしてこの問題を解決したいので、
質問の仕方も含め、間違っていたらいろいろ教えてください。
よろしくお願いいたします。

kvファイルの中の削除buttonのon_pressにdetach_recycleview()を書き込んで、
実行したところ
NameError: name 'detach_recycleview' is not defined
がでました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

私はSelectableXXX系の物は扱ったことは無いですが非SelectableXXX系と同じやり方で一応できたので紹介しますね。RecycleViewにおいて(少なくとも非SelectableXXX系において)は基本的にRecycleView.dataを通して表示するデータを更新します。例えばこれに対してdata.pop(index)data.remove(object)とすることでデータを削除できます。それでSelectableLabel側からどうやって自身が属するRecycleViewを得るかですが、私がよくやっているのがSelectableLabelのinstance.parent.parentです。泥臭いやり方ですが他にやり方が見当たらないのでこうしています。

あとcols = 3はまずい書き方ですね。kivyのpropertyはclass-levelで書き換えてはいけません。必ずinstance.cols = 3とするかKv言語の方でcols: 3と書いてあげてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/02/17 18:47

    ちょっと分からないですね。ここら辺はSelectable系の使い方を知っている人にお願いしたいです。

    キャンセル

  • 2020/02/17 19:04

    公式のSelectable系を使ったsampleに動的にdataの要素を削除するcodeを加えたところ 同じ症状になったので、KIVY側の不具合かもですね。

    キャンセル

  • 2020/02/17 20:52

    回答ありがとうございます。
    いろいろ調べていただきありがとうございました。
    とにかく、行の削除まではできるようになりましたし、他にもいろいろ勉強になりました。
    この問題も引き続き調べようとおもいますが、今回はこれで締めようとおもいます。
    これからアドバイスよろしくお願いいたします。
    ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.63%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる