RecycleView error

18 views
Skip to first unread message

Radosław Głębicki

unread,
Apr 19, 2026, 2:10:46 AM (5 days ago) Apr 19
to Kivy users support
Hi.
I try marked with touch/mouse an element (picture) in RecycleView.
I found recipe somewhere, but doesn't fit to my code. Why? My code has kv lang.

class clMyRecycleView(RecycleView, LayoutSelectionBehavior):
def __init__(self, **kwargs):
super(clMyRecycleView, self).__init__(**kwargs)
class clRowBoxLayout(BL, clMyImage):
sForBulider = f'''<clRowBoxLayout>:
orientation: 'vertical'
<clMyRecycleView>:
canvas.before:
Color:
rgba: {glBckColor}
Rectangle:
pos: self.pos
size: self.size
bar_color: {glSlidCol}
bar_inactive_color: {glInSlCol}
bar_width: {gnWinW/50}
viewclass: 'clMyImage'
data: {gdFILES['lData']}
RecycleGridLayout:
id: grid
cols: {str(gnCol)}
default_size: None, {gnWinW/gnCol*0.75}
default_size_hint: 1, None
spacing: 10,10
padding: 10, 10, {gnWinW/50+5}, 10
size_hint_y: None
height: self.minimum_height
orientation: 'lr-tb'
multiselect: False
touch_multiselect: False'''

With:
<clMyRecycleView>:
Class? I got:  Invalid property name
With:
clMyRecycleView:
I got:
     3:       myClRecycleView:
      4:               canvas.before:
>>    5:                       Color:
      6:                               rgba: (0.1, 0.1, 0.2, 1)
      7:                       Rectangle:
...
Invalid indentation (too many levels)

I try to do that same with RecycleGridLayout. Without success.

I am doing gallery with pictures. I don't know how in that case made: MWE/MRE

Changing to True do nothing.
multiselect: False
touch_multiselect: False

Radek Glebicki

ElliotG

unread,
Apr 19, 2026, 2:54:45 PM (5 days ago) Apr 19
to Kivy users support
It would be easier to help if you share a complete minimal example.  I see a few issues:

In the class declaration the behavior must be listed first:

Change:
class clMyRecycleView(RecycleView, LayoutSelectionBehavior):
to:
class clMyRecycleView(LayoutSelectionBehavior,  RecycleView):


This declaration is also suspect:
class clRowBoxLayout(BL, clMyImage):
I'm not sure what you are trying to do here, but I suspect you would be better off simply putting an Image in a BoxLayout, rather than trying to create a new object that is a BoxLayout and a clImage.  

The convention for class names in python is to use CapWords.  Read: https://pep8.org/#class-names  I would recommend you consider this when naming classes.

Looking at the error statement in the traceback:
     3:       myClRecycleView:
      4:               canvas.before:
>>    5:                       Color:
      6:                               rgba: (0.1, 0.1, 0.2, 1)
      7:                       Rectangle:
...
Invalid indentation (too many levels)
It looks like you are using tab characters in your code that are being expanded.  Things might look fine in your editor, but it is causing a problem.  Make sure the set your code editor so that tabs are converted to 4 spaces.  You might want to do a search replace in your code.

In your python code declaration you are using:
clMyRecycleView 
When you instance the class in kv you are using:
myClRecycleView I would assume these are meant to be the same.

Hope that helps! 

Radosław Głębicki

unread,
Apr 19, 2026, 10:50:12 PM (4 days ago) Apr 19
to Kivy users support
In your python code declaration you are using:
clMyRecycleView 
When you instance the class in kv you are using:
myClRecycleView I would assume these are meant to be the same.

Is that same. I did corrections in post and made mistake.
Indentation is correct. I only add <> and indentation error so kv lang interpreter is wrong?
If class is:
class clMyRecycleView(LayoutSelectionBehavior,  RecycleView):
in kv lang should be between < > ?

f'''<clMyGridLayout>:
orientation: 'vertical'
<clMyRecycleView>:   <---- Even reference to class here like this is correct?
canvas.before:
Color:

Any changes don't help. 

Main reason for that post is how to mark selection in RecycleView for touched/clicked thumbnail.
Before I read about: LayoutSelectionBehavior
I tried to paint frame on canvas around selected thumbnail. But frame was static and scroll didn't move that frame.
So, maybe from that side. How to "pin" frame to RecycleView?

elli...@cox.net

unread,
Apr 20, 2026, 10:15:18 AM (4 days ago) Apr 20
to kivy-...@googlegroups.com
The <ClassName> in angle brackets is referred to as a kivy rule.  It is effectively the same a declaring a class in python.  It is a way to declare the styling for the class.  The rule must be in the far left column.

<RuleDefinitionWidget>:  # This is a kv rule
    size_hint: None, None
    ,,,

MainRootWIdget:
    RuleDefinitionWidget:  # the widget is instanced without <>

To create the "Frame" in the RecycleView you want to do the work in the viewclass.  You could add the ToggleButtonBehavor to the image and make this the viewclass.  You would activate the frame when the image is pressed.  The trick is you need to save the state of the button outside of the viewclass widget.  This is often best done is a separate list.
I'll post a short example later today.


From: kivy-...@googlegroups.com <kivy-...@googlegroups.com> on behalf of Radosław Głębicki <glebicki...@gmail.com>
Sent: Sunday, April 19, 2026 7:50 PM
To: Kivy users support <kivy-...@googlegroups.com>
Subject: [kivy-users] Re: RecycleView error
 
--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/kivy-users/ba767b98-c226-439e-af6e-2219d12674ecn%40googlegroups.com.

Radosław Głębicki

unread,
Apr 20, 2026, 1:25:15 PM (4 days ago) Apr 20
to Kivy users support
I made my own selection method. It is working and it's enough.

Below is part of kv lang from previous post:
<clMyGridLayout>:
...
RecycleView:
...
RecycleGridLayout:

RecycleGridLayout is the "lowest".
On this layout after touch I paint:
...
with koRecGridLay.canvas.before:
Color(*glFrameCol)  # Set color for selection
Rectangle(pos = (nX, nY), size = (nW, nH))
...
pos & size are from data from clicked object. I remember pos & size and after click/touch another pic I paint Rectangle with background color.
Works for me just fine. But I still think in this example::
<clMyGridLayout>:
...
RecycleView:
...
RecycleGridLayout:
you can't make more then one (first) custom class. Strange error from kv lang about depth of indentation.

Thanks for help.

Radek Glebicki

ElliotG

unread,
Apr 20, 2026, 4:52:42 PM (4 days ago) Apr 20
to Kivy users support
You can make more that one Kivy rule. I don't understand what problem you are having.

Based on your description here is a simple example that displays pictures in a RecycleView RecycleGridLayout, and allows selection/deselection of multiple images.  There are two elements here that are tricky.  One is the need to maintain the state of the buttons outside of the widget.  The other is using the RecycleViewDataBehavior to associate the index in the RecycleView data list with the Picture.  Change the path in App.on_start()  to select the correct pictures.

"""
Display all of the pictures in the folder "pictures" and allow the user to select the pictures they are interested in.
The pictures are displayed in a RecycleView RecycleGridLayout.  Select the picture by tapping it.  An outline
will be displayed around the selected picture.  Tapping the selected picture will deselect it.

Pressing the 'paths' button will print the paths of the selected pictures to the console.

The state of the toggle button is saved in the button_state list.  In a recycle view, the same widget may be
reused for multiple items.  Therefore we cannot rely on the widget to save it's state.
"""

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.properties import ListProperty, NumericProperty

from pathlib import Path

kv = """
<Picture>:
    state: app.button_state[self.index]
    canvas.after:
        Color:
            rgba: (0, 1, 0, 1) if self.state == 'down' else (0, 0, 0, 0)
        Line:
            width: 3
            rectangle: (self.x, self.y, self.width, self.height)

RootBoxLayout:
    orientation: 'vertical'
    RecycleView:
        id: rv
        viewclass: 'Picture'
        do_scroll_x: True
        do_scroll_y: True
        bar_width: dp(10)
        scroll_type: ['bars', 'content']
        RecycleGridLayout:
            cols: 10
            id: recycle_grid
            default_size_hint:None, None
            default_size: dp(150), dp(150)
            size_hint: None, None
            size: self.minimum_size
    Button:
        size_hint_y: None
        height: dp(48)
        text: 'Paths'
        on_release: root.print_paths()

"""

class RootBoxLayout(BoxLayout):
    def print_paths(self):
        app = App.get_running_app()
        for pic in app.selected_pictures:
            print(pic)

class Picture(RecycleDataViewBehavior, ToggleButtonBehavior, Image):
    index = NumericProperty()

    def refresh_view_attrs(self, rv, index, data):
        # Called by RecycleView every time this widget is assigned to a data item.
        # Because RecycleView reuses widgets as you scroll, the same Picture widget
        # may represent many different items over time.  This method is our chance
        # to update the widget so it matches the data item at the given index.
        # the index is the position of the item in the data list, and used to index the button_state list.
        self.index = index
        super().refresh_view_attrs(rv, index, data)
        app = App.get_running_app()
        self.state = app.button_state[index]  # restore selected/deselected state for this item

    def on_state(self, instance, value):
        # Called automatically by Kivy whenever the toggle state changes
        # ('normal' = not selected, 'down' = selected).
        app = App.get_running_app()
        app.button_state[self.index] = value  # save the new state so it survives scrolling
        source = app.root.ids.rv.data[self.index]['source']
        if value == 'down':
            if source not in app.selected_pictures:
                app.selected_pictures.append(source)
        elif source in app.selected_pictures:
            app.selected_pictures.remove(source)

class SelectPicApp(App):
    selected_pictures = ListProperty()
    button_state = ListProperty()

    def build(self):
        return Builder.load_string(kv)

    def on_start(self):
        for file in Path(Path().home() / 'OneDrive/Pictures').glob('*.jpg'): # change path for your folder
            self.root.ids.rv.data.append({'source': str(file.absolute())})
            self.button_state.append('normal')

if __name__ == '__main__':
    SelectPicApp().run()
select_pic.py

ElliotG

unread,
Apr 20, 2026, 4:55:14 PM (4 days ago) Apr 20
to Kivy users support
Another suggestion... If you are going to do something like this I would recommend creating thumbnails of the images to improve performance.

Radosław Głębicki

unread,
Apr 20, 2026, 11:37:48 PM (3 days ago) Apr 20
to Kivy users support
Thanks for explanation. Nice and clean code. Mine is big mess. But it works.
I will stay with my method of selection without extra imports.

from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.properties import ListProperty, NumericProperty

Simple canvas.before painting.

About "Another suggestion..." RecycleView is working with part (neccessery part) of data. Is safe about memory. Do I have to worry about thumbnails?
And generating thumbnails for large collections take time.

Radek Glebicki

elli...@cox.net

unread,
Apr 21, 2026, 12:10:29 AM (3 days ago) Apr 21
to kivy-...@googlegroups.com
If you have a performance problem , you can consider setting up thumbnails.  If you don't have a problem, don't bother.

Sent: Monday, April 20, 2026 8:37 PM

To: Kivy users support <kivy-...@googlegroups.com>
Subject: Re: [kivy-users] Re: RecycleView error
 
--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages