Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RecycleView is going through Clock iteration issue when using items with variable height. #6580

Open
goffi-contrib opened this issue Nov 2, 2019 · 2 comments

Comments

@goffi-contrib
Copy link

@goffi-contrib goffi-contrib commented Nov 2, 2019

Versions

  • Python: 3.7.4
  • OS: Arch Linux
  • Kivy: v2.0.0.dev0, git-7947abf, 20191025
  • Kivy installation method: pip install --user git+https://github.com/kivy/kivy.git

Description

I want to use RecycleView in my XMPP client for chat history, to improve performance over BoxLayout. The chat message can be of various length, and the view widget is a BoxLayout including several sub-widgets. When using the RecycleView, I'm running into the following error message:
[CRITICAL] [Clock ] Warning, too much iteration done before the next frame. Check your code, or increase the Clock.max_iteration attribute

I've made a small Python script to reproduce the issue. As viewclass I'm using a BoxLayout and inside a simple Label. I'm using a list comprehension to generate growing texts, so the widget will grow in size (to simulate various message length in a chat).

With variable size, I'm running into the same issue. If I use fixed text, or if I use a fixed size in the BoxLayout height instead of self.minimum_height, the clock issue doesn't happen (but of course I then don't have the desired behaviour).

It seems that RecycleView is badly working with a BoxLayout of variable height.

Code and Logs

from kivy.app import App
from kivy.lang import Builder

KV = '''
<CustomView@BoxLayout>:
    size_hint: 1, None
    height: self.minimum_height
    text: ''
    Label:
        size_hint: 1, None
        text_size: root.width, None
        size: self.texture_size
        text: root.text


RecycleView:
    viewclass: 'CustomView'
    data: [{"text": f"{i} {'test'*i}"} for i in range(300)]
    RecycleBoxLayout:
        id: layout
        default_size: None, None
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
'''

class TestApp(App):
    def build(self):
        return Builder.load_string(KV)

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

Thi code show 300 Label with growing text (row index + "test" repeated multiple times) in a RecycleView.
expected result: the 300 Label are showed properly and the UI is highly reactive when scrolling.
actual result: the message [CRITICAL] [Clock ] Warning, too much iteration done before the next frame. Check your code, or increase the Clock.max_iteration attribute is showed repetitively, the UI is messy and not reactive. The bug is especially visible at the top of the list.

@goffi-contrib

This comment has been minimized.

Copy link
Author

@goffi-contrib goffi-contrib commented Nov 2, 2019

It seems that I've found a workaround by settings the height of the root BoxLayout using on_size in in the Label instead of the self.minimum_size, that then work as expected (still got one [CRITICAL] [Clock ] Warning, too much iteration done before the next frame. Check your code, or increase the Clock.max_iteration attribute though, but without visible consequence in the UI).

Below is the code with the workaround, it's working but still I think self.minimum_height should work and then there is a bug in RecycleView.

Code with workaround:

from kivy.app import App
from kivy.lang import Builder

KV = '''
<CustomView@BoxLayout>:
    size_hint: 1, None
    text: ''
    Label:
        size_hint: 1, None
        on_size: root.height = self.height
        text_size: root.width, None
        size: self.texture_size
        text: root.text


RecycleView:
    viewclass: 'CustomView'
    data: [{"text": f"{i} {'test'*i}"} for i in range(300)]
    RecycleBoxLayout:
        id: layout
        default_size: None, None
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
'''

class TestApp(App):
    def build(self):
        return Builder.load_string(KV)

if __name__ == '__main__':
    TestApp().run()
@goffi-contrib

This comment has been minimized.

Copy link
Author

@goffi-contrib goffi-contrib commented Nov 2, 2019

note: even with the workaround, the UI is not smooth, we can notice a small "jump" when we scroll, probably due to the height change with on_size.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
1 participant
You can’t perform that action at this time.