wimworks
wimworks

Reputation: 323

Kivy: Can't change height of nested GridLayout

I have a simple user interface in kivy that consists of several gridlayouts inside of one large gridlayout.

The Code
This is the kv code for the interface

Builder.load_string('''
<GreyLabel>:
    size_hint_y: None
    height: 30
    canvas.before:
        Color:
            rgba: .7, .7, .7, 1
        Rectangle:
            pos: self.pos
            size: self.size

<ContainerBox>:
    orientation: 'horizontal'

    GridLayout:
        cols: 1
        row_force_default: True
        foo: [self.rows_minimum.update({i: x.height}) for i, x in enumerate(reversed(list(self.children)))]
        ResizingFrame:
            id: Row1
            cols: 1
            GreyLabel:
                text: "Something goes here"
        GridLayout:
            id: Row2
            cols: 1
            Label:
                height: 30
                text: 'Label One'
                canvas.before:
                    Color:
                        rgba: .4, .4, .4, 1
                    Rectangle:
                        pos: self.pos
                        size: self.size
            TextInput:
                height: 30
                multiline: False
                write_tab: False
                hint_text: 'Insert one liner'

        GridLayout:
            id: Row3
            cols: 1
            Label:
                height: 45
                text: 'Label two'
            Button:
                text: 'Button One'
                height: 60
            GridLayout:
                rows: 1
                height: 25
                Button:
                    text: 'Button Two'
                Button:
                    text: 'Button three'
''')

Notice the ResizingFrame item. This is a GridLayout class with the following code

class ResizingFrame(GridLayout):
    c_value = StringProperty('SomeThing goes here')

    def __init__(self, **kwargs):
        super(ResizingFrame, self).__init__(**kwargs)
        Clock.schedule_once(lambda dt: self.adjustHeight(), 1)

    def adjustHeight(self):
        print("ResizingFrame.adjustHeight() before:", self.height)
        self.height = 40
        print("ResizingFrame.adjustHeight() after:", self.height)

You can find the entire code here.

The Goal
I want to be able to change the height of ResizingFrame. The interface starts out looking like this: enter image description here

After 1 second, it should look like this: enter image description here But it's not doing that.

Whenever adjustHeight() runs, it says:
ResizingFrame.adjustHeight() before: 100
ResizingFrame.adjustHeight() after: 40

But this height change never actually happens for some reason. I simply can't change the height of ResizingFrame. Why is this happening? And how can I fix it?

Note
This is related to this question.

I suspect the problem has something to do with the line:
foo: [self.rows_minimum.update({i: x.height}) for i, x in enumerate(reversed(list(self.children)))]
This should set the minimum height of the rows to the height of their children. But as you can see in screenshot 1, that's not happening. It just sets the minimum height to 100 and I can't change the height after that. I can't even increase the height above 100. It's just stuck.

Upvotes: 2

Views: 605

Answers (1)

John Anderson
John Anderson

Reputation: 38837

The reason that you can't change the size of the ResizingFrame, is that its size_hint takes preference over any size changes. So, modifying your adjustHeight method to:

def adjustHeight(self):
    print("ResizingFrame.adjustHeight() before:", self.height)
    self.size_hint_y = None
    self.height = 40
    print("ResizingFrame.adjustHeight() after:", self.height)

will allow the height change to take effect.

Note that without setting size_hint_y to None, the you are changing the height attribute, and that changed value is printed. But once your adjustHeight method completes, then the ResizingFrame height is recalculated and changed back to 100. You can see this by calling your original adjustHeight method more than once (the before height will always be bck to 100).

Upvotes: 3

Related Questions