Search code examples
pythonuser-interfacewidgetkivykivy-language

Dynamic grid in Kivy with each grid element containing multiple widgets


This is my first post here, but I will try to be as detailled as I can. So my application is in python, and involves a grid in kivy, where each element in the grid is supposed to contain 4 additional widgets and possibility for a fifth. The four additional widgets are supposed to be in a cross shape at the edges and the fifth in the middle.

Problem is, whenever I add a sub widget it lands in the bottom left corner on position 0,0 of the main window

So far so good. Right now I am just trying to get even one widget inside another widget to display correctly.

Heres what I attempted:

<GridCell@Label>
    BoxLayout:
        orientation:'horizontal'
        Button:
            text:'One'
            size:10,10
            size_hint:None,None

Building a .kv file for my app, where I would put a box layout inside of it and then a button.

Also I tried the following class configuration:

class GridCell(Label):

def __init__(self, **kwargs):
    super().__init__(**kwargs)
    self.root = FloatLayout()
    self.button = Button(text="test")
    self.button.x = self.root.x
    self.button.center_y = self.root.center_y
    self.root.add_widget(self.button)
    self.add_widget(self.root)

Also did not work.

I am adding the grid cells by just calling .add on the grid with a newly created widget for each iteration of a for loop.

All the child widgets are apparently created, but they all land in the bottom left corner!

This is the whole code of the gui right now:

import kivy
import World
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import Color, Rectangle

kivy.require('1.10.0')



class GridCell(Label):

def __init__(self, **kwargs):
    super().__init__(**kwargs)
    self.root = FloatLayout()
    self.button = Button(text="blargh")
    self.button.x = self.root.x
    self.button.center_y = self.root.center_y
    self.root.add_widget(self.button)
    self.add_widget(self.root)

def on_size(self, *args):
    self.canvas.before.clear()

    if self.id is "cliff":
        with self.canvas.before:
            Color(249 / 255, 6 / 255, 6 / 255, 0.3)
            Rectangle(pos=self.pos, size=self.size)
    if self.id is "goal":
        with self.canvas.before:
            Color(6 / 255, 6 / 255, 249 / 255, 0.3)
            Rectangle(pos=self.pos, size=self.size)
    if self.id is "start":
        with self.canvas.before:
            Color(11 / 255, 174 / 255, 6 / 255, 0.3)
            Rectangle(pos=self.pos, size=self.size)
    if self.id is "normal":
        with self.canvas.before:
            Color(119 / 255, 115 / 255, 115 / 255, 0.3)
            Rectangle(pos=self.pos, size=self.size)




class GameGridApp(App):

def __init__(self, **kwargs):
    super().__init__(**kwargs)
    self.grid = GridLayout(cols=8, rows=5)
    self.load_into()

def load_into(self):
    world = World.World(8, 5)
    world.build_gamegrid()

    for cell in world.gamegrid:
        name = str(cell.name)
        grid_cell = GridCell()
        grid_cell.text = name

        if cell.start:
            grid_cell.id = "start"
        if cell.goal:
            grid_cell.id = "goal"
        if cell.cliff:
            grid_cell.id = "cliff"
        if cell.field:
            grid_cell.id = "normal"

        self.grid.add_widget(grid_cell)

def build(self):
    return self.grid


customLabel = GameGridApp()
customLabel.run()

Solution

  • I may give an idea , that create a 'subgrids' object and a 'main grid' object that contain the 'subgrids'. These two objects would be GridLayout objects.

    Here is a simple example in python2.7 :

    import kivy
    from kivy.app import App
    from kivy.uix.gridlayout import GridLayout
    from kivy.uix.label import Label
    
    class SubGrids(GridLayout):
        def __init__(self):
            GridLayout.__init__(self, cols=3, rows=3);
            self.add_widget(Label(text='1st'));
            self.add_widget(Label(text=''));
            self.add_widget(Label(text='2nd'));
            self.add_widget(Label(text=''));
            self.add_widget(Label(text='3rd'));
            self.add_widget(Label(text=''));
            self.add_widget(Label(text='4th'));
            self.add_widget(Label(text=''));
            self.add_widget(Label(text='5th'));
    class Grids(GridLayout):
        def __init__(self):
            GridLayout.__init__(self, cols=2, rows = 2);
            self.add_widget(SubGrids());
            self.add_widget(SubGrids());
            self.add_widget(SubGrids());
            self.add_widget(SubGrids());
    class Example(App):
        def build(self):
            return Grids()
    
    if __name__ == '__main__':
        x = Example();
        x.run();
    

    Hope this gives an idea.

    enter image description here