How to update a custom property in kivy while making custom widgets.

182 views
Skip to first unread message

UmFqYXQ

unread,
Jul 6, 2020, 2:00:03 AM7/6/20
to Kivy users support
Hello everyone, I'm trying to make a custom button with rounded corners and a border width but whenever I try to update the border width based on some events like on_press, on_release, etc. the border width or corner radius is initialized to what it was.

Here is my code:-

from kivy.uix.button import Button
from kivy.properties import ListProperty
from kivy.properties import NumericProperty
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App


class CustomButton(Button):

# defaults
 border_color = ListProperty([1, 1, 1, 1])
corner_radius = NumericProperty(0)
bg_color = ListProperty([0, 0, 0, 1])
border_width = NumericProperty(0)


Builder.load_string('''
<CustomButton@Button>:

# should I define border_color, corner_radius, bg_color and border_width
# here or within my python script like I did here?

background_color: 0, 0, 0, 0
background_normal: ''
background_down: ''

canvas.before:
Color:
rgba: self.border_color
RoundedRectangle:
size: self.size
pos: self.pos
radius: [self.corner_radius]

Color:
rgba: self.bg_color
RoundedRectangle:
size: [i - 2 * self.border_width for i in self.size]
pos: [i + self.border_width for i in self.pos]
radius: [self.corner_radius - self.border_width if self.corner_radius != 0 else 0]

''')


class RootWidget(FloatLayout):
pass


Builder.load_string('''
<RootWidget>:
CustomButton:
size_hint: 0.2, 0.1
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
text: 'HELLO'
border_width: 0.1 * self.height
on_press:
self.border_width = 0.2 * self.height

''')


class TestApp(App):
def build(self):
return RootWidget()


TestApp().run()


When I press the button the border_width changes as expected but the instant I change the height of the window it becomes what it was. Also I don't want to the border width to depend on just one thing i.e. height in this case I want the flexibility to change as per some expression like (0.1*self.height - 0.02 * self.width)/0.5*some_widget.some_attribute) something like that.

This happens only with properties that depend on some other property because when I change the border_color or bg_color it changes but it is not the case with corner radius.
Also when I don't initialize border_width inside the RootWidget and initialize it on some event like on_press it updates.

I have tried to implement the same with Line rounded_rectangle but its not looking good (the surfaces which should be flat are not completly flat and other things like this).

I guess when I initialize the value of border_width inside RootWidget kivy creates some method and that method is fired whenever the height changes thus updating the border_width.
Is this assumption correct?
If not please tell me what is kivy doing in the background.

One more thing to ask as this is a custom widget the way I defined it is correct or not, I mean defining all properties inside the class and styling stuff in kv file or it should it be defined in pure python script or pure kv lang? (Just asking in case I need to reuse this in another project or I want to give it to someone) in short what is the correct way of defining/making a custom widget?

Please tell me what is going on!

Thank you for your precious time and help.

Elliot Garbus

unread,
Jul 6, 2020, 11:14:25 AM7/6/20
to kivy-...@googlegroups.com

Here is what I changed.

  1. You had CustomButton defined in kv as a dynamic class derived from Button.  Either define the class in kv as a dynamic class, or define the class in python, not both.  I removed the dynamic class from the kv code.
  2. Define the behavior in on_release: to restore the image width
  3. Moved on the on_release and on_press definitions to the kv definition
  4. Added on_press and on_release statements to the instance to show they work with the on_press and on_release defined in the class.

 

 

from kivy.uix.button import Button
from kivy.properties import ListProperty
from kivy.properties import NumericProperty
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App


class CustomButton(Button):
   
# defaults
   
border_color = ListProperty([1, 1, 1, 1])
    corner_radius = NumericProperty(
0)
    bg_color = ListProperty([
0, 0, 0, 1])
    border_width = NumericProperty(
0)


Builder.load_string(
'''
<CustomButton>:


    # should I define border_color, corner_radius, bg_color and border_width
    # here or within my python script like I did here?

    background_color: 0, 0, 0, 0
    background_normal: ''
    background_down: ''

    canvas.before:
        Color:
            rgba: self.border_color
        RoundedRectangle:
            size: self.size
            pos: self.pos
            radius: [self.corner_radius]
        Color:
            rgba: self.bg_color
        RoundedRectangle:
            size: [i - 2 * self.border_width for i in self.size]
            pos: [i + self.border_width for i in self.pos]
            radius: [self.corner_radius - self.border_width if self.corner_radius != 0 else 0]
    border_width: 0.1 * self.height
    on_press: self.border_width = 0.2 * self.height
    on_release: self.border_width = 0.1 * self.height
'''
)


class RootWidget(FloatLayout):
   
pass


Builder.load_string('''

<RootWidget>:
    CustomButton:
        size_hint: 0.2, 0.1
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}
        text: 'HELLO'
        on_press: print('Button Pressed')
        on_release: print('Button Released')
'''
)


--
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/90de4622-749f-4324-ae75-53e1a4e9bb9eo%40googlegroups.com.

 

Reply all
Reply to author
Forward
0 new messages