community
community copied to clipboard
Color Constants Do Not Work in Canvas
Software Versions
- Python: 3.8
- OS: macOS Big Sur
- Kivy: 2.1.0
- Kivy installation method: compile and install from GitHub source
Describe the bug
Using the pure Python way in kivy docs [Adding a Background to a Layout] (https://kivy.org/doc/stable/guide/widgets.html#adding-widget-background), if I declare GREEN = Color(0, 1, 0, 1)
and use it in place of the Color(0, 1, 0, 1)
in the canvas instructions, it does not work. The background renders as a white rectangle instead of green.
Expected behavior Expect identical behavior to original sample code.
Code To Reproduce Error/Bug
from kivy.app import App
from kivy.graphics import Color, Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
GREEN = Color(0, 1, 0, 1) # want to use constants for readability/scalability
class RootWidget(FloatLayout):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
self.add_widget(
Button(
text="Hello World",
size_hint=(0.5, 0.5),
pos_hint={"center_x": 0.5, "center_y": 0.5},
)
)
class MainApp(App):
def build(self):
self.root = root = RootWidget()
root.bind(size=self._update_rect, pos=self._update_rect)
with root.canvas.before:
GREEN # why does this not work?! :(
# Color(0, 1, 0, 1) # green; colors range from 0-1 not 0-255
self.rect = Rectangle(size=root.size, pos=root.pos)
return root
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
if __name__ == "__main__":
MainApp().run()
hmm i do not think this is a bug
with
is used in a context manager, ( ie root.canvas.before
), so GREEN is actually not available there
you can do
root.canvas.before.add(GREEN)
with root.canvas.before:
self.rect = Rectangle(size=root.size, pos=root.pos)
but im sure there is a better way
After some trial-and-error, I found a better way:
with root.canvas.before:
Color(*GREEN)
self.rect = Rectangle(size=root.size, pos=root.pos)
Above works even though GREEN
alone does not. Likely it has something to do with how the Python interpreter works.
So GREEN
is available within the context manager, since GREEN
is declared as a "global variable".
How that context manager works is clear to me. If you instantiate a graphics instruction (Color
in this case) inside the context manager, it will be automatically added to the canvas.
GREEN = Color(0, 1, 0, 1) # outside the context manager, you need to add it to a canvas manually.
root.canvas.add(GREEN)
with root.canvas:
GREEN = Color(0, 1, 0, 1) # inside the context manager, automatically added to the canvas
@gottadiveintopython:
I concur with the above. Merely mentioning a value (i.e. GREEN
) isn't going to have any effect. You need to be executing something (e.g. Colour.__init__()
) for the context manager to have a chance to change behaviour.
But this is going to be subtle for newbies. The documentation doesn't attempt to address it.
I am making this Issue about documenting the behaviour, rather than the behaviour being wrong.