Kivy ScreenManager ve RecycleView beraber kullanımı

Arkadaşlar merhaba;

Aşağıda kivy"nin sitesinden almış olduğum örnek RecycleView kodları bulunuyor. Burda yaptığım tek değişiklik multiselect özelliğini False yapmak.

link = https://kivy.org/docs/api-kivy.uix.recycleview.html

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

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


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
        if is_selected:
            print("selection changed to {0}".format(rv.data[index]))
        else:
            print("selection removed for {0}".format(rv.data[index]))


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


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

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

Burada da ScreenManager ile ilgili almış olduğum örnek kodlar var

link = https://kivy.org/docs/api-kivy.uix.screenmanager.html

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen

# Create both screens. Please note the root.manager.current: this is how
# you can control the ScreenManager from kv. Each screen has by default a
# property manager that gives you the instance of the ScreenManager used.
Builder.load_string("""
<MenuScreen>:
    BoxLayout:
        Button:
            text: 'Goto settings'
            on_press: root.manager.current = 'settings'
        Button:
            text: 'Quit'

<SettingsScreen>:
    BoxLayout:
        Button:
            text: 'My settings button'
        Button:
            text: 'Back to menu'
            on_press: root.manager.current = 'menu'
""")

# Declare both screens
class MenuScreen(Screen):
    pass

class SettingsScreen(Screen):
    pass

# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SettingsScreen(name='settings'))

class TestApp(App):

    def build(self):
        return sm

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

Ve son olarak yukarıdaki iki örnek kodları editleyerek kendi yazmış olduğum kodlar

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

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang.builder import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.properties import BooleanProperty

Builder.load_string('''<TestScreen>:
    viewclass: 'SelectableLabel'
    SelectableRecycleBoxLayout:
        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

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

 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
        if is_selected:
            print("selection changed to {0}".format(rv.data[index]))
        else:
            print("selection removed for {0}".format(rv.data[index]))

class TestScreen(Screen, RecycleView):

    def __init__(self, **kwargs):
        super(TestScreen, self).__init__(**kwargs)
        self.data = [{'text': str(x)} for x in range(100)]

class TestScreen1(Screen):
    pass

sm = ScreenManager()
sm.add_widget(TestScreen(name= 'Screen1'))
sm.add_widget(TestScreen1(name= 'Screen2'))

class MainApp(App):

    def build(self):
        return sm

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

Burada yapmaya çalıştığım şey şu RecycleView içindeki öğelerin herhangi birine tıklandığında Screen2 ye geçsin. Ancak kodları incelediğinizde göreceğiniz üzere RecycleView’i yukarıdaki gibi bir ScreenManager da görüntülediğim zaman seçim yapılamıyor. Yardımcı olabilirseniz çok sevinirim arkadaşlar, herkese iyi çalışmalar.

1 Beğeni
# -*- coding: utf-8 -*-

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang.builder import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.properties import BooleanProperty

Builder.load_string('''<TestScreen>:
    viewclass: 'SelectableLabel'
    SelectableRecycleBoxLayout:
        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

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

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):
            #ileri()
            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:
            ileri()
            print("selection changed to {0}".format(rv.data[index]))
        else:
            print("selection removed for {0}".format(rv.data[index]))

class TestScreen(Screen, RecycleView):

    def __init__(self, **kwargs):
        super(TestScreen, self).__init__(**kwargs)
        self.data = [{'text': str(x)} for x in range(100)]

class TestScreen1(Screen):
    pass

sm = ScreenManager()
sm.add_widget(TestScreen(name= 'Screen1'))
sm.add_widget(TestScreen1(name= 'Screen2'))

def ileri():
    sonraki = sm.next()
    pcrr = sm.get_screen(sonraki)
    sm.current = sonraki
class MainApp(App):

    def build(self):
        return sm

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

Kodlarinizi inceledim.Elimden geleni yaptım.(ama sorunu cozdugumden hic de emin degilim maalesef.ama bi inceleyin isterseniz.recycleview kullanimini bilmiyorum.ama yine de yardimci olmak istedim.)(yapamadigimi dusunmemin nedeni,1 den 100 e kadar kutucuklar olusturuyorlar ya,işte benim kod,1,2,3… seceneklerine bastiginizda olmuyor da 90 nıncı ve yakınlarındaki seceneklere basınca istediginiz oluyor.(bu durumu cozemedim.once 1 e basın 20 vb ye basın,sonra bi 90. numaraya vb basın.Gorursunuz,sorun yoksa ve varsa bilgilendirebilirsiniz.(sorun varsa cozebilecegimi de zannetmiyorum ya.iste)

Ama sundan adım kadar eminim.Kodlara dikkat ederseniz soyle ifadeler ekledim.

def ileri():
    sonraki = sm.next()
    pcrr = sm.get_screen(sonraki)
    sm.current = sonraki

Ve

def apply_selection(self, rv, index, is_selected):
        ''' Respond to the selection of items in the view. '''
        self.selected = is_selected
        if is_selected:
            ileri()
            print("selection changed to {0}".format(rv.data[index]))
        else:
            print("selection removed for {0}".format(rv.data[index]))

ileri fonksiyonu bu babda hayati onem tasıyor.Soyle ki:

# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder

kv = """
<pencere1>:
    name: "p1"
    BoxLayout:
        orientation: "vertical"
        Label:
            text: "ilk pencere"

        Button:
            text: "ikinci pencereye git"
            on_touch_down: app.ileri_git() 

<pencere2>:
    name: "p2"
    BoxLayout:
        orientation: "vertical"
        Label:
            text: "ikinci pencere"
        Button:
            text: "son pencereye git"
            on_touch_down: app.ileri_git()

<pencere3>:
    name: "p3"
    BoxLayout:
        orientation: "vertical"
        Label:
            text: "son pencere"
        Button:
            text: "ilk pencereye git"
            on_touch_down: app.ileri_git()

"""
class pencere1(Screen):
    pass

class pencere2 (Screen):
    pass

class pencere3(Screen):
    pass

class pencere_yonetimi(App):

    def ileri_git(self):        #bu fonksiyon olmadan ileriki screen e gecemezsin
        sonraki = self.pcr_yonetim.next()     #bu bolumu anlayamazsanız sorun,cevaplamaktan seref duyarım 
        pcr = self.pcr_yonetim.get_screen(sonraki)
        self.pcr_yonetim.current = sonraki

    def build(self):
        Builder.load_string(kv)
        self.pcr_yonetim = ScreenManager()    #burada once ScreenManager sınıfını ornekleyelim
        
        pcr_1 = pencere1()   #
        pcr_2 = pencere2()   # Screen sınıfları orneklenmeli.Cunku add_widget ile screenmanager'imize ekleyecegiz
        pcr_3 = pencere3()   #

        

        self.pcr_yonetim.add_widget(pcr_1)
        self.pcr_yonetim.add_widget(pcr_2) #ekleme bolumunu zaten goruyorsun
        self.pcr_yonetim.add_widget(pcr_3)

        return self.pcr_yonetim #en son return et screenmanageri

pencere_yonetimi().run()

Anlayamadıgınız yerde bilgim neticesinde yardimci olmaya calısırım.

1 Beğeni