2017-10-14 4 views
0

ListViews를 사용하는 Kivy의 이전 버전으로 작성된 프로그램이 있습니다. ListView를 사용하면 어댑터를 통해 선택한 노드를 얻는 것이 매우 쉬웠습니다. 그러나 RecycleView를 사용하여이를 수행하는 방법이 훨씬 명확하지 않습니다. 이제, rv.layout_manager.selected_nodes을 사용하여 선택한 값을 얻을 수 있지만 실제 노드에 관심이있는 시간도 있습니다. 또한 다음 스 니펫을 사용하여 노드를 생성 할 수는 있지만 RecycleView의 실제 노드는 아닙니다.Kivy Recycleview에서 선택된 노드 가져 오기

opts = rv.layout_manager.view_opts 
for i in range(len(rv.data)): 
    s = rv.view_adapter.get_view(i, rv.data[i], opts[i]['viewclass']) 
    print s.text, s.selected 

저는 RecycleView에서 선택한 노드를 가져 오는 방법을 찾는 데 관심이 있습니다.

전체 코드 :

import random 
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.properties import BooleanProperty 
from kivy.uix.recycleboxlayout import RecycleBoxLayout 
from kivy.uix.behaviors import FocusBehavior 
from kivy.uix.recycleview.layout import LayoutSelectionBehavior 

#Aside: the code in the string would need to be indented back one tab, but it's like this for SO formatting 
Builder.load_string(''' 
<SelectableLabel>: 
    # Draw a background to indicate selection 
    canvas.before: 
     Color: 
     rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1) 
     Rectangle: 
      pos: self.pos 
      size: self.size 
<RV>: 
    viewclass: 'SelectableLabel' 
    SelectableRecycleBoxLayout: 
     key_selection: "True" 
     default_size: None, dp(56) 
     default_size_hint: 1, None 
     size_hint_y: None 
     height: self.minimum_height 
     orientation: 'vertical' 
     multiselect: False 
     touch_multiselect: True 
     touch_deselect_last: True 
''') 


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior, 
           RecycleBoxLayout): 
    ''' Adds selection and focus behaviour to the view. ''' 


class SelectableLabel(RecycleDataViewBehavior, Label): 
    ''' Add selection support to the Label ''' 
    index = None 
    selected = BooleanProperty(False) 
    selectable = BooleanProperty(True) 

    def refresh_view_attrs(self, rv, index, data): 
     ''' Catch and handle the view changes ''' 
     self.index = index 
     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 


class RV(RecycleView): 
    def __init__(self, **kwargs): 
     super(RV, self).__init__(**kwargs) 
     self.data = [{'text': str(random.random())} for x in range(20)] 


class TestApp(App): 
    def build(self): 
     self.rv = RV() 
     self.rv.layout_manager.bind(selected_nodes=self.selectionChange) 
     return self.rv 

    def selectionChange(self, inst, val): 
     print inst, val 

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

답변

1

우리에게 코드를 보여주십시오.

class TestRecycleView(RecycleView): 

    def __init__(self, **kwargs): 
     super(TestRecycleView, self).__init__(**kwargs) 
     self.data = [{'name': 'test', 'ind':0,'selected': 0}] 

class TestBox(RecycleDataBehaviour, BoxLayout): 
    def action(self, boss): 
     if boss.data[self.ind]['selected'] == 0: 
     boss.data[self.ind]['selected'] = 1 
     else: 
     boss.data[self.ind]['selected'] = 0 

KV : 사용자가 매개 변수를 추가 할 수 rv.data에서 = 노드가 선택되지 않고 0과 1 것은이 예이다 때 '선택'경우

<TestRecycleView>: 
    viewclass: 'TestBox' 
    RecycleBoxLayout: 
     default_size: None, 440 
     default_size_hint: 1, None 
     size_hint_y: None 
     height: self.minimum_height 
     orientation: 'vertical' 
<TestBox>: 
    Button: 
     on_press: root.action(root.parent.parent) 

I 물론 당신은의 selectedLabel 값을 인쇄 할 것을 이해 :

class TestApp(App): 
    def build(self): 
     self.rv = RV() 
     self.rv.layout_manager.bind(selected_nodes=self.selectionChange) 
     return self.rv 

    def selectionChange(self, inst, val): 
     print self.rv.data[val[0]]['text'] 

proof(image link)

+0

내 실수. 잘못된 예제 파일을 나열했습니다. 코드는에서 편집됩니다. 내 목표는 recycleView.layout_manager 밖으로 선택한 노드를 얻는 것입니다. –

+0

나는 나의 대답을 갱신했다, 희망은 당신이 원하는 것이다. @PistolPete –

+0

그것은 내가 틀린 장소에서 찾고 있다고 밝혀졌다. 내 목표는 선택된 위젯을 얻는 것이었고''rv.layout_manager''를보고있었습니다. ''rv.view_adapter.views''를보고 있어야한다는 것이 밝혀졌습니다. 그러나 도움에 감사드립니다. –