Reputation: 10884
I'm trying to create a grid of widgets with each "cell" widget having a rectangle I can change the color of later. When I run the code below with the line grid.add_widget(Button(text=str(i)))
the buttons fill the window (as in the docs). However, when I use my Cell
widget as in grid.add_widget(Cell())
all the widgets are bunched in the lower left corner (position=[0,0]
, size=[100,100]
). I found this question Kivy: Add raw Widget to GridLayout (as opposed to Image, Button, etc) and changed my Cell
class to inherit from Layout
instead of Widget
but that didn't help things. Any ideas on what I'm doing wrong? What I'd like is a grid of colored rectangles.
Versions
[INFO ] [Kivy ] v1.9.1
[INFO ] [Python ] v2.7.6 (default, Jun 22 2015, 17:58:13)
Code
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.layout import Layout
from kivy.graphics import Rectangle, Color
XSIZE=2
YSIZE=2
class Cell(Layout):
def __init__(self, *args, **kwargs):
super(Cell, self).__init__(*args, **kwargs)
with self.canvas:
Rectangle(size=self.size, pos=self.pos)
Color((0.2, 0.2, 0.2, 1.0))
class GameApp(App):
def build(self):
grid = GridLayout(rows=YSIZE, cols=XSIZE, size=Window.size)
for i in xrange(4):
print 'i={}'.format(i)
# grid.add_widget(Cell())
grid.add_widget(Button(text=str(i)))
return grid
if __name__ == '__main__':
GameApp().run()
Upvotes: 5
Views: 2710
Reputation: 5405
I will show an example on how you can achieve this.
I will create a grid class, and add the cell widgets to it.
But I will only use one canvas (the gridlayouts canvas).
So the cell class will contain an InstructionGroup, rather than make multiple canvases.
To be able to set size, position and color of each cell later, those attributes must be attributes of the cell class.
The attributes will be set in MyGrid
's set_attributes
method.
First when the app is running, you can get the positions of the cells, hence I use the Clock.schedule_once
method. That will execute the next frame.
And to demonstrate how to change the colors, I create a Clock.schedule_interval
, to animate the colors of the cells with random colors.
So here is the example:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Rectangle, Color, InstructionGroup
from kivy.clock import Clock
from random import uniform
XSIZE=2
YSIZE=2
class Cell(Widget):
def __init__(self, i, **kwargs):
super(Cell, self).__init__(**kwargs)
self.ig = InstructionGroup()
self.rect = Rectangle()
self.color = Color(0.2, 0.2, 0.2*i)
self.ig.add(self.color)
self.ig.add(self.rect)
class MyGrid(GridLayout):
def __init__(self,**kwargs):
super(MyGrid,self).__init__(**kwargs)
self.rows=YSIZE
self.cols=XSIZE
for i in xrange(4):
self.add_widget(Cell(i))
self.canvas.add(self.children[0].ig)
Clock.schedule_once(self.set_attributes)
Clock.schedule_interval(self.change_color,1)
def set_attributes(self,dt):
for i in self.children:
i.rect.pos = i.pos
i.rect.size = i.size
def change_color(self,dt):
for i in self.children:
i.color.rgb = (uniform(0.0,1.0),uniform(0.0,1.0),uniform(0.0,1.0))
class GameApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
GameApp().run()
Upvotes: 1