1

I'm making a kivy app to find the rhyming words for a word entered by the user. It displays all the rhyming words as OneLineListItems in an MDList which is inside a kivy RecycleView. On clicking on one of these OneLineListItems it displays the definition of the word on the right-hand side of the screen. However, when I click on a OneLineListItem its definition takes very long to appear and sometimes it lags so badly that the app closes. Am I doing something wrong or is it just my computer? Code below:

from kivymd.app import MDApp
from kivy.lang import Builder
from kivymd.uix.label import MDLabel
from kivymd.uix.list import OneLineListItem
import pronouncing
import enchant
from PyDictionary import PyDictionary

dictionary = PyDictionary()
d = enchant.Dict("en_US")

kv = """
Screen:
    input:input
    scroll:scroll
    word:word
    defs:defs
    MDGridLayout:
        rows: 1
        cols: 2
        MDGridLayout:
            rows: 2
            cols: 1
            MDFloatLayout:
                MDTextField:
                    id:input
                    size_hint: (.4, None)
                    height: 26
                    multiline: False
                    on_text_validate: app.rhyme()
                    hint_text: "Search"
                    mode: "rectangle"
                    pos_hint: {"center_x": .25, "center_y": .85}
                    font_name: "DejaVuSans.ttf"
                    text_size: self.size
            MDFloatLayout:
                RecycleView:
                    size_hint: 0.85,1.5
                    bar_width: dp(15)
                    bar_height: dp(40)
                    scroll_type: ["content"]
                    pos_hint: {"center_x": 0.45, "center_y": 0.93}
                    MDList:
                        id: scroll
                
        
        MDBoxLayout:
            id:defs
            orientation: "vertical"
            md_bg_color: 0, 1, 0.2, 1
            MDLabel:
                id: word
                text: ""
                text_size: self.size
                

"""


class RhymeApp(MDApp):
    played = []
    x_turn = True

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

    def rhyme(self):
        raw_rhymes = pronouncing.rhymes(self.screen.input.text)
        rhymes = []
        [rhymes.append(x) for x in raw_rhymes if x not in rhymes and x[-1] != "." and d.check(x)]
        self.screen.scroll.clear_widgets()
        for i in rhymes:
            self.screen.scroll.add_widget(
                OneLineListItem(text=f"{i}".capitalize(), on_release=self.dictionary)
            )

    def dictionary(self, btn):
        nl = '\n'
        self.screen.defs.clear_widgets()
        self.screen.word.text = btn.text.capitalize()
        meaning = dictionary.meaning(btn.text, disable_errors=True)
        if meaning is None:
            self.screen.defs.add_widget(
                MDLabel(text=f"Sorry, no meaning for that word.",
                        text_size="self.size")
            )
        else:
            for key in meaning:
                self.screen.defs.add_widget(
                    MDLabel(text=f"Part of speech: {key} {nl}Meaning: {nl}{nl}{meaning[key][0].capitalize()}.",
                            text_size="self.size")
                )


if __name__ == "__main__":
    RhymeApp().run()

Can someone please help?

Raed Ali
  • 549
  • 1
  • 6
  • 22
  • 1
    You are not using [**`RecycleView`**](https://kivy.org/doc/stable/api-kivy.uix.recycleview.html) properly. Perhaps that's why it's behaving like `ScrollView` which gets slower as its no. of child widgets grow. – ApuCoder Jan 24 '22 at 19:00
  • @ApuCoder Thank you very much, could you please post how to make proper use of it as an answer? I am new to RecycleView and am not sure how to proceed. – Raed Ali Jan 24 '22 at 22:38

1 Answers1

1

First create a custom class for the data-class like following:

class ListItem(OneLineListItem):
    # Here define all the necessary attrs., methods apart from the defaults (if you need any).

Now in your .kv initialize RecycleView as,

                RecycleView:
                    id: scroll
                    #size_hint: 0.85,1.5
                    bar_width: dp(15)
                    bar_height: dp(40)
                    scroll_type: ["content"]
                    #pos_hint: {"center_x": 0.45, "center_y": 0.93}
                    viewclass: "ListItem"
                    RecycleBoxLayout:
                        default_size: None, dp(48)
                        default_size_hint: 1, None
                        size_hint_y: None
                        height: self.minimum_height
                        orientation: 'vertical'

Now you are ready to feed RecycleView with you data as,

    def rhyme(self):
        ...
        self.screen.ids.scroll.data = [
            {"text" : f"{i}".capitalize()}
        for i in rhymes]
ApuCoder
  • 2,795
  • 2
  • 3
  • 19
  • Thanks again for your help, I added what you said, but now the OneLineListItems do not display. – Raed Ali Jan 25 '22 at 11:28
  • Did you remove the line `self.screen.scroll.clear_widgets()` ? If not removed, this line will remove the data container `RecycleBoxLayout`, and you will see nothing. – ApuCoder Jan 25 '22 at 12:50
  • I trust I find you in a very good mood this morning, would you be able to help me speed up the adding of each word's definition? Its widget generation is also very slow. I can ask a separate question for it if you want. – Raed Ali Jan 26 '22 at 11:23
  • I'll suggest you to try it yourself. Asking for help may turn out to be good in some situations, but it's far better to be self-sufficient. If you're eager to learn it, do some research, look into the kivy docs etc. You will definitely learn something by doing. Here is a relevant [post](https://stackoverflow.com/questions/70718810/kivy-recycleview-not-scrolling-smoothly/70719494#70719494) you may find helpful. You may always find someone helpful, but make sure you did your best. Please don't make seeking help a habit. – ApuCoder Jan 26 '22 at 14:55