Search code examples
pythonkivyscrollview

Why Kivy ScrollView children of child are not scrollable?


This is a part of a python-script running kivy:

class someclass(Widget):
# code
# code
Clock.schedule_interval(self.timeandlog, 0.1)
self.x = 20
def timeandlog(self,dt):
    if condition == True: # 
       self.ids.pofchild.add_widget(Label(text=logmsg, pos = (10, self.x)))
       self.x = self.x + 10   ### just playing with position 
       condition = False  

kv file:

<someclass>

    #somelabels and buttons:

    ScrollView:
        do_scroll_x: False
        do_scroll_y: True
        pos: root.width*0.3, root.height*0.7
        size: root.width*0.8, root.height*0.7 
        Widget:
            cols: 1 
            spacing: 10
            id: pofchild

Now I know the ScrollView accepts one Widget so I added just one with an id: pofchild then I added labels inside it with self.ids.pofchild.add_widget(Label() and changing every new label's pos with pos=(20, self.x) but the labels are not scrollable and only fill the widget height then stop appearing. What are right attributions so they will be scrollable?


Solution

  • In general, when you want a Widget to contain other Widgets, you should use a Layout Widget. A simple Widget does not honor size_hint or pos_hint, so the children of a simple Widget often end up with the default size of (100,100) and the default position of (0,0).

    So, a good start is to change:

    class someclass(Widget):
    

    to something like:

    class Someclass(FloatLayout):
    

    Note that the class name starts with a capital letter. Although it does not cause any difficulties in your example, it can produce errors when you use kv and your classname starts with lower case.

    Similarly, the child of the ScrollView is also normally a Layout. A possibility is GridLayout, like this:

        GridLayout:
            size_hint_y: None
            height: self.minimum_height
            cols: 1 
            spacing: 10
            id: pofchild
    

    Keys attributes here are the size_hint_y: None and height: self.minimum_height. They allow the GridLayout to grow as more children are added, and its height will be calculated as the minimum height needed to contain the children.

    Then, you can add children like this:

    self.ids.pofchild.add_widget(Label(text=logmsg, pos=(10, self.x), size_hint_y=None, height=50))
    

    Since we are expecting the GridLayout to calculate its minimum height, we must provide an explicit height for its children, thus the size_hint_y=None, height=50.