Reputation: 449
I would like to give all of the widgets on the screen a white canvas. I know how to create the intended canvas in KV
but in this case I must use Python code.
In my code, I tried self.cavas.add(...)
and in the code below, I use with self.canvas:
. Both attempts resulted in a canvas being drawn in the corner of the screen, rather than inside of the widgets.
How do I put a canvas to be inside of every widget using Python code?
Code:
from kivy.app import App
from kivy.core.window import Window
from kivy.graphics.context_instructions import Color
from kivy.graphics.vertex_instructions import Rectangle
from kivy.lang import Builder
from random import random
from kivy.uix.button import Button
from kivy.animation import Animation
from kivy.clock import Clock
class LittleButtons(Button):
dur = 2
def reup(self, *args):
Animation.cancel_all(self)
Animation(pos_hint = {'center_x': random(), 'center_y': random()}, duration = self.dur).start(self)
def __init__(self, **kwargs):
super(LittleButtons, self).__init__(**kwargs)
self.pos_hint = {'center_x': random(), 'center_y': random()}
self.size_hint = None, None
self.width = random() * (Window.width / 20)
self.height = self.width
self.background_color = [0,0,0,.05]
with self.canvas:
Color(rgba = [1,1,1,.2])
Rectangle(pos = self.pos, size = self.size)
Animation(pos_hint = {'center_x': random(), 'center_y': random()}, duration = self.dur).start(self)
Clock.schedule_interval(self.reup, self.dur)
KV = Builder.load_string("""
#:import Factory kivy.factory.Factory
Screen:
FloatLayout:
on_parent:
(lambda ltext: [self.add_widget(Factory.LittleButtons(text=ltext)) for i in range (150)])('hi!')
Button:
background_color: 0,0,0,0
canvas:
Color:
rgba: 0,1,1,1
Rectangle:
pos: self.pos
size:self.size
""")
class MyApp(App):
def build(self):
return KV
if __name__ == '__main__':
MyApp().run()
Upvotes: 2
Views: 1120
Reputation: 38822
The problem is that in the LittleButtons
__init__()
method, its position is still the default of (0,0), so the position of the Rectangle
is set to (0,0). When you use KV
, it cleverly binds the Rectangle
position to the LittleButtons
position when you reference self.pos
. Unfortunately, in a .py
file, you must provide that binding yourself. So, here is a modification of your LittleButtons
that should handle the position changes:
class LittleButtons(Button):
dur = 2
def reup(self, *args):
Animation.cancel_all(self)
Animation(pos_hint = {'center_x': random(), 'center_y': random()}, duration = self.dur).start(self)
def __init__(self, **kwargs):
self.rect = None
super(LittleButtons, self).__init__(**kwargs)
self.pos_hint = {'center_x': random(), 'center_y': random()}
self.size_hint = None, None
self.width = random() * (Window.width / 20)
self.height = self.width
self.background_color = [0,0,0,.05]
with self.canvas:
Color(rgba = [1,1,1,.2])
self.rect = Rectangle(pos = self.pos, size = self.size)
Animation(pos_hint = {'center_x': random(), 'center_y': random()}, duration = self.dur).start(self)
Clock.schedule_interval(self.reup, self.dur)
def on_pos(self, instance, pos):
if self.rect is not None:
self.rect.pos = pos
The changes are the addition of a self.rect
attribute and a on_pos
method.
You can add something similar if you need to handle changing size
.
Upvotes: 2