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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

3001閲覧

(kivy)RecycleViewに組み込んだCheckBoxの状態の取得方法について

roshi10011

総合スコア8

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

1グッド

1クリップ

投稿2018/01/30 08:29

編集2018/02/01 02:09

###やりたいこと
kivyを使用して,ID管理アプリを作成しようとしています.
何かしらの手段によって,現在登録されているIDの一覧を取得・表示し,管理したいと考えています.

###現状
とりあえずIDを取得した状態で,RecycleViewを用いてIDのリストを表示します.
リストにはチェックボックスがあり,それらをチェックした後,リスト外にある「削除」ボタンを押下することでリストから削除するアクションを実装することを検討しております.

モック

###困っていること
表外にある削除ボタンを押下した際に,チェックがONの行だけ削除したいですが,そもそもボタン押下時にリスト内のでチェックボックスの状態を取得できず,思った通りの実装ができていません.
削除ボタン押下時(on_press)の際に,Rowで定義したCheckBoxのidを取得する方法についてご教示お願いいたします。
(Widgetの親子関係について不勉強で大変申し訳ございません。。。)
以下は使用しているkvファイルのソースコードになります。

lang

1<Manager>: 2 rv: rv 3 BoxLayout: 4 BoxLayout: 5 orientation: "vertical" 6 Label: 7 size_hint_y: 0.2 8 text: "登録ID一覧" 9 color: 0, 0, 0, 1 10 canvas.before: 11 Color: 12 rgba: 0.75, 0.75, 0.75, 1 13 Rectangle: 14 pos: self.pos 15 size: self.size 16 BoxLayout: 17 BoxLayout: 18 orientation: "vertical" 19 BoxLayout: 20 size_hint_y: 0.2 21 Label: 22 text: "ID" 23 Label: 24 text: "権限" 25 Label: 26 text: "削除" 27 BoxLayout: 28 canvas: 29 Color: 30 rgba: 0.85, 0.85, 0.85, 1 31 Rectangle: 32 size: self.size 33 pos: self.pos 34 orientation: 'vertical' 35 RecycleView: 36 id: rv 37 scroll_type: ['bars', 'content'] 38 scroll_wheel_distance: dp(56) 39 bar_width: dp(10) 40 viewclass: 'Row' 41 RecycleBoxLayout: 42 default_size: None, dp(56) 43 default_size_hint: 1, None 44 size_hint_y: None 45 height: self.minimum_height 46 orientation: 'vertical' 47 spacing: dp(2) 48 AnchorLayout: 49 size_hint_x: 0.3 50 anchor_x: "center" 51 anchor_y: "center" 52 Button: 53 text: "削除" 54 size: 80, 40 55 size_hint: None, None 56 on_press: root.delete(num,a) # 押下時に表中でチェックの入った行を削除したい 57 58<Row@BoxLayout>: 59 canvas.before: 60 Color: 61 rgba: 0.5, 0.5, 0.5, 1 62 Rectangle: 63 size: self.size 64 pos: self.pos 65 data: ("","","") 66 Label: 67 id: num 68 text: root.data[0] 69 Label: 70 id: a 71 text: root.data[1] 72 CheckBox:

python

1from kivy.app import App 2from kivy.config import Config 3from kivy.lang import Builder 4from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition 5from kivy.uix.boxlayout import BoxLayout 6from kivy.properties import StringProperty, ObjectProperty, BooleanProperty 7from kivy.core.text import LabelBase, DEFAULT_FONT 8from kivy.resources import resource_add_path 9Config.set('graphics', 'width', '800') 10Config.set('graphics', 'height', '600') 11Config.set('input', 'mouse', 'mouse,disable_multitouch') # 右クリック赤丸消去 12Config.set('kivy', 'exit_on_escape', '0') # kivy ESC無効化 13 14# Path of Fonts 15resource_add_path('/usr/share/fonts/truetype/takao-gothic') 16LabelBase.register(DEFAULT_FONT, 'TakaoGothic.ttf') # 日本語が使用できるように日本語フォントを指定する 17 18# Path of KV_Lang 19Builder.load_file("./Account_for_teratail.kv") 20 21# Setting Screen 22SM = ScreenManager(transition=NoTransition()) 23 24 25class Manager(Screen): 26 rv = ObjectProperty() 27 28 def on_enter(self): 29 self.rv.data = [{'data': ("000000", "manager", "pass")}] 30 31 def delete(self, id, per): 32 print(id, per) 33 34 35# class Row(BoxLayout): 36# is_checked = BooleanProperty(False) 37# id = StringProperty() 38# permission = StringProperty() 39 40 41class GUIApp(App): 42 """ 43 実行クラス 44 """ 45 def build(self): 46 SM.add_widget(Manager(name="manager")) 47 self.title = 'アカウント管理ソフト' 48 return SM 49 50 51if __name__ == '__main__': 52 GUIApp().run() 53 54

###備考
python: 3.4.2
kivy: 1.10.0

TANUKIpro👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

一応できたので貼って置きます。

python3

1from kivy.app import App 2from kivy.config import Config 3from kivy.lang import Builder 4from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition 5from kivy.uix.boxlayout import BoxLayout 6from kivy.properties import StringProperty, ObjectProperty, BooleanProperty 7from kivy.core.text import LabelBase, DEFAULT_FONT 8from kivy.resources import resource_add_path 9Config.set('graphics', 'width', '800') 10Config.set('graphics', 'height', '600') 11Config.set('input', 'mouse', 'mouse,disable_multitouch') # 右クリック赤丸消去 12Config.set('kivy', 'exit_on_escape', '0') # kivy ESC無効化 13 14# Path of Fonts 15resource_add_path('/usr/share/fonts/truetype/takao-gothic') 16LabelBase.register(DEFAULT_FONT, 'TakaoGothic.ttf') # 日本語が使用できるように日本語フォントを指定する 17 18 19# Path of KV_Lang 20Builder.load_file("./Account_for_teratail.kv") 21 22# Setting Screen 23SM = ScreenManager(transition=NoTransition()) 24 25 26class Manager(Screen): 27 rv = ObjectProperty() 28 29 def on_enter(self): 30 self.rv.data = [ 31 {'id': "000000", 'permission': "manager", 'is_checked': True, }, 32 {'id': "000001", 'permission': "manager", 'is_checked': False, }, 33 {'id': "000002", 'permission': "manager", 'is_checked': False, }, 34 ] 35 36 def delete(self): 37 # print('DELETE') 38 self.rv.data = list(filter( 39 lambda item: not item['is_checked'], self.rv.data)) 40 41 42class Row(BoxLayout): 43 id = StringProperty() 44 permission = StringProperty() 45 is_checked = BooleanProperty(False) 46 47 def on_checkbox_press(self, checkbox): 48 # print('on_checkbox_press', checkbox.state, checkbox.active) 49 rv = SM.get_screen('manager').rv 50 for item in rv.data: 51 if item['id'] == self.id: 52 # print('Found', item) 53 item['is_checked'] = checkbox.active 54 return 55 56 57class GUIApp(App): 58 """ 59 実行クラス 60 """ 61 def build(self): 62 SM.add_widget(Manager(name="manager")) 63 self.title = 'アカウント管理ソフト' 64 return SM 65 66 67if __name__ == '__main__': 68 GUIApp().run() 69
<Manager>: rv: rv BoxLayout: BoxLayout: orientation: "vertical" Label: size_hint_y: 0.2 text: "登録ID一覧" color: 0, 0, 0, 1 canvas.before: Color: rgba: 0.75, 0.75, 0.75, 1 Rectangle: pos: self.pos size: self.size BoxLayout: BoxLayout: orientation: "vertical" BoxLayout: size_hint_y: 0.2 Label: text: "ID" Label: text: "権限" Label: text: "削除" BoxLayout: canvas: Color: rgba: 0.85, 0.85, 0.85, 1 Rectangle: size: self.size pos: self.pos orientation: 'vertical' RecycleView: id: rv scroll_type: ['bars', 'content'] scroll_wheel_distance: dp(56) bar_width: dp(10) viewclass: 'Row' RecycleBoxLayout: default_size: None, dp(56) default_size_hint: 1, None size_hint_y: None height: self.minimum_height orientation: 'vertical' spacing: dp(2) AnchorLayout: size_hint_x: 0.3 anchor_x: "center" anchor_y: "center" Button: text: "削除" size: 80, 40 size_hint: None, None on_press: root.delete() <Row>: canvas.before: Color: rgba: 0.5, 0.5, 0.5, 1 Rectangle: size: self.size pos: self.pos Label: text: root.id Label: text: root.permission CheckBox: active: root.is_checked on_press: root.on_checkbox_press(self)

投稿2018/02/03 03:39

編集2018/02/03 04:19
gottadiveintopy

総合スコア736

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

roshi10011

2018/02/05 00:29

ご回答いただき、ありがとうございます! 動作確認させていただいたところ、当初のやりたいことと同じこと確認できました。 Kivyの、Widgetの組み立て方次第で柔軟に対応できることを改めて実感致しました。。。 ベストアンサーとさせていただきます。
guest

0

.pyファイルが無いので確認はできていませんが多分こんな感じでRowを用意してやれば

python3

1 2class Row(BoxLayout): 3 is_checked = BooleanProperty(False) 4 id = StringProperty() 5 permission = StringProperty()

text

1 2<Row>: 3 canvas.before: 4 Color: 5 rgba: 0.5, 0.5, 0.5, 1 6 Rectangle: 7 size: self.size 8 pos: self.pos 9 Label: 10 text: root.id 11 Label: 12 text: root.permission 13 CheckBox: 14 active: root.is_checked 15 on_active: root.is_checked = args[1]

後はrv.dataからいつでもデータを得られると思いますよ。

python3

1for item in rv.data: 2 if item['is_checked']: 3 # チェックが付いている時に行いたい処理 4 print(item['id'], item['permission'])

rv.dataを介してデータの読み書きを行うほうが、データを表示する為のRowというWidgetに依存しないのでいいと思います。

投稿2018/01/31 11:19

編集2018/01/31 11:50
gottadiveintopy

総合スコア736

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

roshi10011

2018/02/01 02:07

ご回答ありがとうございます。 pyファイルがないとのことでしたので、更新いたしました。 ご回答頂いたようにRowウィジェットを修正したところ、rv.dataに保存されているデータが表示されなくなりました。 現在作成しているpyファイルでは、rv.dataはメインスクリーン(現状ではManagerスクリーン)表示時に定義しているのですが、Rowクラス中で定義・データ入力したほうがよろしいのでしょうか?
roshi10011

2018/02/01 07:55

rv.dataにチェックボックスの状態を保存するように変更し、CheckBoxのon_activeをトリガーにしてチェックボックスの状態を更新する、というやや力技な方法で上記問題を解決することができました。 しかしながら、RecycleView中でCheckBoxを使用した際に、意図していないCheckBoxの状態が変化する、といった問題が発生致しました。 [過去の質問](https://teratail.com/questions/100622) [stack_overflowでの同様の質問](https://stackoverflow.com/questions/44943288/checkbox-in-kivy-recycleview-clicking-one-impacts-others) 自身のkivyのコーディング能力では解決できない問題であると判断したため、現状の仕様を変更することとなりました。 ご回答頂き、誠にありがとうございました。
gottadiveintopy

2018/02/01 11:37

自分なりに色々試してますが、 CheckBoxの状態が変化したらrv.dataを更新、rv.dataが更新されたらCheckBoxを更新しないといけないので、循環Loopになる問題があります。ユーザーのClickによるCheckBoxの変化とrv.dataの更新によるCheckBoxの変化を区別する事がこの問題の解決法だと思いますが、その為に今試しているCheckBoxのon_press()を使う方法がCheckBoxの仕様ではなく実装に依存したコードになりそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問