Search code examples
pythonpython-3.xpython-2.7kivykivy-language

Python/Kivy : not working properly vertical scrollbar in dynamic row


I have two files demo.py and demo.kv
I have a button +Add More which add row dynamic.I am trying to add vertical scrollbar in dynamic row using ScrollView:.But its not working properly.
its mean when i add row in scrollview that row having extra space in scrollview i want add rows without any spacing.

ScrollView:
            BoxLayout:
                orientation: "horizontal"
                size_hint_y: None
                height: 500

                Rows:
                    id: rows

demo.py

import kivy
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty

Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (500, 400)

class user(Screen):

    def add_more(self):
        self.ids.rows.add_row()


class Row(BoxLayout):
    button_text = StringProperty("")


class Rows(BoxLayout):
    orientation = "vertical"
    row_count = 0

    def __init__(self, **kwargs):
        super(Rows, self).__init__(**kwargs)
        self.add_row()

    def add_row(self):
        self.row_count += 1
        self.add_widget(Row(button_text=str(self.row_count)))


class Test(App):

    def build(self):
        self.root = Builder.load_file('demo.kv')
        return self.root


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

demo.kv

<Button@Button>:
    font_size: 15
    font_name: 'Verdana'

<Label@Label>:
    font_size: 15
    font_name: 'Verdana'

<TextInput@TextInput>:
    font_size: 15
    font_name: 'Verdana'
    padding_y: 3


<Row>:
    GridLayout:
        cols: 2
        row_force_default: True
        row_default_height: 40

        Button:
            text: root.button_text
            size_hint_x: None
            top: 200

        Button:
            text: 'World 1'
            width: 300


user:

    BoxLayout:
        orientation: "vertical"
        padding : 20, 5


        BoxLayout:
            orientation: "horizontal"
            #padding : 10, 10
            spacing: 10, 10
            size: 450, 40
            size_hint: None, None

            Label:
                size_hint_x: .2
                text: "Test 1"
                text_size: self.size
                valign: 'bottom'
                halign: 'center'

            Label:
                size_hint_x: .8
                text: "Test 2"
                text_size: self.size
                valign: 'bottom'
                halign: 'center'


        ScrollView:
            BoxLayout:
                orientation: "horizontal"
                size_hint_y: None
                height: 500

                Rows:
                    id: rows


        BoxLayout:
            orientation: "horizontal"
            size_hint_x: .2
            size_hint_y: .2

            Button:
                text: "+Add More"
                on_press: root.add_more()


        BoxLayout:
            orientation: "horizontal"
            padding : 10, 5
            spacing: 10, 10
            size_hint: .5, .35
            pos_hint: {'x': .25, 'y':.25}

            Button:
                text: 'Ok'

            Button:
                text: 'Cancel'

any help would be greatly appreciated.


Solution

  • If I have understood what you want, you have too many nested Layouts, that are unnecessary. Rows should be the main layout of your ScrollView.

    On the other hand, Rows should always have the lowest possible height to contain their widgets (minimun_height property), not a fixed size.

    Demo.py:

    from kivy.uix.screenmanager import Screen
    from kivy.app import App
    from kivy.lang import Builder
    from kivy.core.window import Window
    from kivy.uix.boxlayout import BoxLayout
    from kivy.properties import StringProperty
    
    Window.clearcolor = (0.5, 0.5, 0.5, 1)
    Window.size = (500, 400)
    
    class User(Screen):
    
        def add_more(self):
            self.ids.rows.add_row()
    
    
    class Row(BoxLayout):
        button_text = StringProperty("")
    
    
    class Rows(BoxLayout):
        row_count = 0
    
        def __init__(self, **kwargs):
            super(Rows, self).__init__(**kwargs)
            self.add_row()
    
        def add_row(self):
            self.row_count += 1
            self.add_widget(Row(button_text=str(self.row_count)))
    
    
    class Test(App):
    
        def build(self):
            self.root = Builder.load_file('Demo.kv')
            return self.root
    
    
    if __name__ == '__main__':
        Test().run()
    

    Demo.kv:

    <Button@Button>:
        font_size: 15
        font_name: 'Verdana'
    
    <Label@Label>:
        font_size: 15
        font_name: 'Verdana'
    
    <TextInput@TextInput>:
        font_size: 15
        font_name: 'Verdana'
        padding_y: 3
    
    
    <Row>:
        size_hint_y: None
        height: self.minimum_height
        height: 40
    
        Button:
            text: root.button_text
            size_hint_x: None
            top: 200
    
        Button:
            text: 'World 1'
            width: 300
    
    <Rows>:
        size_hint_y: None
        height: self.minimum_height
        orientation: "vertical"
    
    User:
        BoxLayout:
            orientation: "vertical"
            padding : 20, 5
    
    
            BoxLayout:
                orientation: "horizontal"
                #padding : 10, 10
                spacing: 10, 10
                size: 450, 40
                size_hint: None, None
    
                Label:
                    size_hint_x: .2
                    text: "Test 1"
                    text_size: self.size
                    valign: 'bottom'
                    halign: 'center'
    
                Label:
                    size_hint_x: .8
                    text: "Test 2"
                    text_size: self.size
                    valign: 'bottom'
                    halign: 'center'
    
    
            ScrollView:
                Rows:
                    id: rows
    
    
            BoxLayout:
                orientation: "horizontal"
                size_hint_x: .2
                size_hint_y: .2
    
                Button:
                    text: "+Add More"
                    on_press: root.add_more()
    
    
            BoxLayout:
                orientation: "horizontal"
                padding : 10, 5
                spacing: 10, 10
                size_hint: .5, .35
                pos_hint: {'x': .25, 'y':.25}
    
                Button:
                    text: 'Ok'
    
                Button:
                    text: 'Cancel'
    

    enter image description here