Change dinamically the radius of a Rounded Rectangle

331 views
Skip to first unread message

Barbarur

unread,
Aug 1, 2022, 11:10:06 AM8/1/22
to Kivy users support
Hello everyone,

I'm testing the way on how to change dynamically radius of a Rounded Rectangle.

The rounded rectangle is part of a widget I add on the screen. The size of the rectangle depends on the size of the screen, and the radius should be also dynamically changed.

On the example below:
First rectangle, red:
The radius is dependent on a variable (a tuple)  of the widget, the radius seems not changing dynamically as expected.

Second rectangle, green:
Similar as the first rectangle, but this time the variable for the radius is a integer. Still radius doesn't change.

Third rectangle, blue:
The radius is dependent on the width of the widget and both change correctly as intended.

I'm trying to make the radius changing dynamically based on a variable, as on my project I expect this variable to be proportional of other parts of the widget, and also reuse it's value. So it would be easier if I can just setup a variable and then use the variable whenever I need it.


Side question: Getting the size of the screen in kivy always confuse me. Previously I was able to get the right size of the screen during on_enter. But while preparing this testing code, on_enter I still get just 100 as width size. only when on_size triggers for second time (also I don't know why it triggers twice), I get the correct size of the screen.

Thank you in advance for the help.


Test Code:

from kivy.lang import Builder
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen, ScreenManager, FadeTransition
from kivymd.app import MDApp


Builder.load_string("""
<ThisWidget>:
size_hint: None, None
canvas.before:
Color:
rgba: 1, 0, 0, 1
RoundedRectangle:
pos: self.pos
size: self.size
radius: self.frame
Color:
rgba: 0, 1, 0, 1
RoundedRectangle:
pos: self.pos[0] + self.width / 6, self.pos[1] + self.height / 6
size: self.width / 1.5, self.height / 1.5
radius: [self.frame_2]
Color:
rgba: 0, 0, 1, 1
RoundedRectangle:
pos: self.pos[0] + self.width / 4, self.pos[1] + self.height / 4
size: self.width / 2, self.height / 2
radius: [self.width / 10]
""")


class ThisWidget(ButtonBehavior, BoxLayout):
frame = [0]
frame_2 = 0

def __init__(self, **kwargs):
super(ThisWidget, self).__init__(**kwargs)
self.pos = (100, 100)

def resize(self, w, h, r):
self.size = (w, h)
self.frame = [r]
self.frame_2 = r


class ThisScreen(Screen):
l = []
def on_size(self, *args):
print(f'on_size width: {self.width}')
self.w = self.width
self.h = self.height
for i in self.l:
i.resize(self.width / 2, self.height / 3, self.width / 50)

def on_enter(self, *args):
print(f'on_enter width: {self.width}')
wg = ThisWidget()
wg.resize(self.width / 2, self.height / 3, self.width / 50)
self.add_widget(wg)
self.l.append(wg)

class TestApp(MDApp):
sm = None

def build(self):
self.sm = ScreenManager(transition=FadeTransition(duration=.3))
self.sm.add_widget(ThisScreen(name='ScreenOne'))
self.sm.current = 'ScreenOne'
return self.sm


TestApp().run()


Elliot Garbus

unread,
Aug 1, 2022, 11:50:57 AM8/1/22
to kivy-...@googlegroups.com

The key is to use a kivy property to change the value.  This will automatically create a binding that updates the value of the radius when the property changes.  You do not get this behavior with a python variable.  Below is an interactive example.  Adjust the slider to set the radius.

 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.properties import NumericProperty

kv =
"""
BoxLayout:
    orientation: 'vertical'
    AnchorLayout:
        RRLabel:
            id: rrlabel
            text: 'Rounded Rectangle'
            size_hint: None, None
            size: 200, 200
            color: 'black'
            canvas.before:
                Color:
                    rgba: 1, 1, 1, 1
                RoundedRectangle:
                    size: self.size
                    pos: self.pos
                    radius: [self.radius] * 4
    Slider:
        size_hint_y: None
        height: 50
        max: 100
        on_value: rrlabel.radius = self.value
    Label:
        size_hint_y: None
        height: 50
        text: f'The radius value = {rrlabel.radius:0.2f}'
"""


class RRLabel(Label):
    radius = NumericProperty()


class RRApp(App):
   
def build(self):
       
return Builder.load_string(kv)


RRApp().run()

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/15b031be-8935-4be6-b637-ea46a9da5fefn%40googlegroups.com.

 

Elliot Garbus

unread,
Aug 1, 2022, 11:55:12 AM8/1/22
to kivy-...@googlegroups.com

Side question: Getting the size of the screen in kivy always confuse me. Previously I was able to get the right size of the screen during on_enter. But while preparing this testing code, on_enter I still get just 100 as width size. only when on_size triggers for second time (also I don't know why it triggers twice), I get the correct size of the screen.

 

The default size for a widget is 100 x 100.  You are seeing the initial value of the screen, then when the layout sets the size of the Screen size, you are seeing it get set by the Layout.

 

 

From: Barbarur
Sent: Monday, August 1, 2022 8:10 AM
To: Kivy users support
Subject: [kivy-users] Change dinamically the radius of a Rounded Rectangle

 

Hello everyone,

--

Barbarur

unread,
Aug 9, 2022, 2:35:31 AM8/9/22
to Kivy users support
Hi Elliot,

Thanks a lot. I see now it's working on my test code when using the Numeric property.I tried before Numeric properties, but I didn't see much difference with with normal variables. Now I get it.

One thing about the properties I hope you can explain; If I use a numeric property on Screen#1 and on Screen#2 I want to refer to the value of that property. When I refer to it, I don't get its value, but an object. What is the best way to refer the values of properties (numeric or any other) between screens?

Regarding the 'on_size'. After more testing, I see it only runs twice  for the first screen of the app. For any other screen, on_size only runs once, unless the window change. Interesting to know. I think this also got on the way of other test code I did before, giving me funny results.

Elliot Garbus

unread,
Aug 9, 2022, 11:26:13 AM8/9/22
to kivy-...@googlegroups.com

Share your code.  I don’t know why your seeing the object rather than the value.

 

When you refer to properties across screens you want to access them using the screenmanager method get_screen().  Read: https://kivy.org/doc/stable/api-kivy.uix.screenmanager.html?highlight=get_screen#kivy.uix.screenmanager.ScreenManager.get_screen

 

In python to access one screens attributes from another:

 

self.manager.get_screen(‘other_screen’).other_screens_property

 

in kv, doing this from a kivy rule with a Screen as the root, would be similar:

 

root.manager.get_screen(‘other_screen’).other_sceeens_property

 

manager is an attribute of the Screen, it holds the ScreenManager the screen is under.

Barbarur

unread,
Aug 15, 2022, 3:45:05 AM8/15/22
to Kivy users support
Hi Elliot,

Thanks a lot for your help.

This issue I had it +1month ago. At that time I found a work around and moved on working on my project. Now I've been trying to reproduce the issue to make a sample test code, but this time everything has been working fine.

I think probably the issue it was related with the information you shared, and I wasn't accessing the properties correctly. I remember I did try several ways on accessing variables between classes before I settle with 'get_screen()'.

Thanks again for the clarifications.

ElliotG

unread,
Aug 15, 2022, 8:58:06 AM8/15/22
to Kivy users support
Glad to hear you have things working!
Reply all
Reply to author
Forward
0 new messages