Question

I would like to create some kind of dynamic tile layout where the widgets would have an adjustable size (such as Appy Geek, which is like Flipboard but with resizable tiles).

I've been using this class, which is a bit dirty (with all the Clock.Schedule_once, but I couldn't make it work otherwise).

My problem is that I can't get this class to work dynamically. For example, using a simple main.py :

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from kivy.app import App
from kivy.uix.button import Button


class MainApp(App):
    def add(self, gd, x, y, w, h):
        print gd, x.text, y.text, w.text, h.text
        x = int(x.text)
        y = int(y.text)
        w = int(w.text)
        h = int(h.text)
        gd.set_widget(Button(text='B %i %i' % (x, y)), x, y, w, h)
        gd.do_layout()

MainApp().run()

and a simple .kv :

#:kivy 1.8.0
#:import SGridLayout SGridLayout
#:import SGridLayoutCell SGridLayout

BoxLayout:
    orientation: 'vertical'
    SGridLayout:
        cols: 5
        rows: 4
        id: gd
    BoxLayout:
        orientation: 'horizontal'
        size_hint_y: None
        height: '50dp'
        TextInput:
            text: '1'
            id: x
        TextInput:
            text: '1'
            id: y
        TextInput:
            text: '1'
            id: w
        TextInput:
            text: '1'
            id: h
        Button:
            text: 'Add'
            on_press: app.add(gd, x, y, w, h)
        Button:
            text: 'Remove'

When adding a button, it appears on the bottom left, even though we've chosen another pos with the input. But as soon as we resize the window, the button goes to its real pos.

Example : When adding a 1x1 button at the pos (1,1), and then resizing the window a little bit (Imgur album)

So... Any ideas ? TYA :)

Was it helpful?

Solution

Okay, I looked through your code and noticed that the widget's pos and size attributes are only updated when its respective cell's attributes are updated. I modified the SGridLayoutCell's add_widget method, as following, to make it work:

def add_widget(self, widget, row=0, col=0, width=1, height=1):
    self.swidth = width
    self.sheight = height
    self.row = row
    self.col = col
    self.widget = widget

    # They are updated now!
    widget.pos = self.pos
    widget.size = self.size

    self.bind(pos=widget.setter('pos'))
    if self.swidth == 1:
        self.bind(width=widget.setter('width'))
    else:
        widget.width = self.width * self.swidth
    if self.sheight == 1:
        self.bind(height=widget.setter('height'))
    else:
        widget.height = self.height * self.sheight
    Clock.schedule_once(self.post_init)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top