Reputation: 31
I think there is a way to do it in kivy rather than going round the python code.
my code in the kv file:
ButtonBehavior:
source: "round-icon.png"
the app crashes saying
AttributeError: 'ButtonBehavior' object has no attribute 'register_event_type'
round-icon.png
is circular icon. The last thing that I will appreciate recommendation, How to set this button to certain size is the window?
Upvotes: 3
Views: 8214
Reputation: 12179
You need to make a custom rule(/class) that has the behavior and you need to include Image
as el3phanten stated, yet it won't work only that way, because it'll return you a missing class.
Kv language creates a widget from either already registered classes, or custom classes, which may be Python + Kv (that thing you define in both files), or kv only(dynamic). I guess your intention is the dynamic one, so I'll go this way:
from kivy.app import App
from kivy.lang import Builder
kv = """
<Test@ButtonBehavior+Image>:
canvas:
Color:
rgba: 1, 0, 0, .3
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
Button:
Test:
source: 'image.png'
"""
class TestApp(App):
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
TestApp().run()
The behavior needs to be first similar to inheriting in Python, then you may add another parts, such as Image
.
There's however a big problem for you in this implementation, which is visible with the Rectangle
in my example. That is an area that captures every touch, which means you might have a circular image, yet the touch are is still a rectangle.
To get around that you'll need to check for a collision, thus you need to switch from dynamic class to the one that's defined even in Python, so that you can make custom collisions. Example.
That, however, might be really costly even for a single button, therefore a better solution is using something like this:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import NumericProperty
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.image import Image
kv = """
<RoundButton>:
canvas:
Color:
rgba: 1, 0, 0, .3
Rectangle:
size: self.size
pos: self.pos
Color:
rgba: 0, 0, 1, 1
Rectangle:
size:
[self.size[0] - root.OFFSET_x,
self.size[1] - root.OFFSET_y]
pos:
[self.pos[0] + root.OFFSET_x / 2.0,
self.pos[1] + root.OFFSET_y / 2.0]
BoxLayout:
Button:
RoundButton:
source: 'image.png'
on_release: print('Release event!')
"""
class RoundButton(ButtonBehavior, Image):
OFFSET_x = NumericProperty(100)
OFFSET_y = NumericProperty(200)
def on_touch_down(self, touch):
left = touch.x >= self.pos[0] + self.OFFSET_x / 2.0
down = touch.y >= self.pos[1] + self.OFFSET_y / 2.0
up = touch.y <= self.pos[1] + self.size[1] - self.OFFSET_y / 2.0
right = touch.x <= self.pos[0] + self.size[0] - self.OFFSET_x / 2.0
if left and down and up and right:
print('collided!')
self.dispatch('on_release')
else:
print('outside of area!')
class TestApp(App):
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
TestApp().run()
or a really low number of points to a better area coverage, yet higher than for a simple rectangle.
How to set this button to certain size is the window?
Use size_hint
or directly Window.size
to manipulate your widget's size. size_hint
is definitely better unless you want to have everything in Window, i.e. without any proper Layout
Upvotes: 0
Reputation: 5405
Try importing Image also:
Image+ButtonBehavior:
source: "round-icon.png"
Upvotes: 1