rotate entire widget, not only its canvas - kivy

In this example, we can see a rotation of the canvas. But clicking the button's corners isn't registered. How can I rotate the entire button?

You can probably override its collide_point method to account for the rotation by transforming the touch coordinates.
If you use the widget system (e.g. putting the Button in a Scatter), the collision is taken care of for you.

Based on inclement's answer, I've created a button on a scatter layout, which has its hitbox set correctly.
from kivy.app import App
from kivy.lang import Builder
kv = '''
FloatLayout:
ScatterLayout:
size_hint: None, None
size: 200, 200
pos_hint: {'center_x': .5, 'center_y': .5}
rotation: 45
do_rotation: False
do_scale: False
do_translation: False
Button:
text: 'hello world'
'''
class RotationApp(App):
def build(self):
return Builder.load_string(kv)
RotationApp().run()
I used scatter layout instead of scatter, because it passes its size to children widgets. The do_x: False aren't needed in this example, because button intercepts touching events, but if I placed a label, it would move on touch.

Related

How to remove outer layer margin from MDTextField?

I want to have two MDTextFields touching each other at their bottom and top border
The MDTextField has an outer layer which prevents them from touching each other. Is there a property to remove this margin? Margins I want to remove(black rectangles):
MDTextfields colored to show the margins
Lines I want to touch:
Arrows pointing at parts of borders I want to merge together
BoxLayout:
orientation:"vertical"
size_hint: 1, None
height:textfield1.height+ textfield2.height
MDTextField:
id:textfield1
hint_text: "Rectangle mode"
mode: "rectangle"
MDTextField:
id:textfield2
hint_text: "Rectangle mode"
mode: "rectangle"
Final product would be something like this:
Here
Thank you!
I can't comment due to rep. This worked for me:
spacing:"-10dp" in BoxLayout

Kivy Access Touch Object

I'm new to kivy and I want to access the touch Object without overwriting motion event functions like on_touch_down(self,touch), on_touch_up(), etc..
I want to access touch.pos in order to dynamically draw lines on an Image in a Scatter Class.
Simplified my kv file looks like the following:
<Map#Scatter>:
source: None
do_rotation: False
Image:
id: main_image
source: root.parent.parent.parent.parent.map_path
allow_stretch: True
keep_ratio: True
size_hint_y: None
size_hint_x: None
width: self.parent.width
height: self.parent.width/self.image_ratio
<Zoom>:
id: zoom_class
Map:
id: map_class
<RoomMarkerScreen>:
id: room_marker_screen
AnchorLayout:
rows: 2
AnchorLayout:
anchor_x: 'center'
anchor_y: 'top'
Zoom:
id: zoom_class
AnchorLayout:
anchor_x:'center'
anchor_y: 'bottom'
Button:
text: "Fix/Unfix Map"
size_hint: 0.5, 0.05
on_press:
root.fix_unfix(root.fix)
Knowing that Class Zoom Inherits from FloatLayout, how can I access Touch Object in Zoom?
Thanks in advance!
If I take the touch.pos from the event motion functions, they will be overwritten and I won't be able use the drag and scale features that came with the Scatter Class.
Whenever you write a function that exists in a super class, you should call that that super class method, otherwise, you will be interfering in the functioning of that super class (for example, DragBehavior). So, I suggest trying something like:
class Zoom(FloatLayout):
fixed_map = BooleanProperty(False)
def on_touch_down(self, touch):
print(touch.pos)
return super(Zoom, self).on_touch_down(touch)
And returning True from a on_touch_down() method stops all further dispatching of that touch event, so other widgets do not see that event. See the documentation.
Also, from the same documentation:
on_touch_down(), on_touch_move(), on_touch_up() don’t do any sort of
collisions. If you want to know if the touch is inside your widget,
use collide_point().

Transparent animated graphics in Kivy

I am new to Kivy and want to create a widge graphic image of a tank with a transparent cutout that "fills" with another graphic image of the product. How do I stack 2 graphic images, one with a transparent layer, on top of one another to get this effect? I have created this with a circle/rectangle and fill color, but I want both a custom foreground image and a custom fill image.
You can stack Image widgets by simply placing them at the same position. For example, in kv you can do:
FloatLayout:
Image:
source: 'fill.png'
size_hint: 0.25, 0.25
pos_hint: {'center_x':0.5, 'center_y':0.5}
allow_stretch: True
Image:
source: 'tank.png'
size_hint: 0.25, 0.25
pos_hint: {'center_x':0.5, 'center_y':0.5}
allow_stretch: True
This will show the tank.png with the fill.png showing through any transparent areas of tank.png.

Kivy:Can't put 'BorderImage' at the specified position

(1) By using the following kv file version was able to place BorderImagewidget at the specified position..
<Screen>:
ProgressBar:
max: 100
pos_hint: {'top':0.86, 'x':0.01}
size_hint_x: 0.49
size_hint_y: 0.1
canvas:
BorderImage:
border: (10, 10, 10, 10)
pos: self.x, self.center_y
size: self.width, 8
source: '0.png'
(2) But, the following Pure Python code that should realize the same function as (1) doesn't work properly.BorderImagewidget is placed at the bottom of the screen.
pos_hint={'top':0.86,'x':0.01} doesn't work.
I think that how to specify pos=(bar.x, bar.center_y) is not good because bar.center_y value is different from the code of (1).
class BarWidget(FloatLayout):
def __init__(self, **kwargs):
super(BarWidget, self).__init__(**kwargs)
self.build()
def build(self):
bar = ProgressBar(pos_hint={'top':0.86,'x':0.01}, max=100, size_hint_x=0.49, size_hint_y=0.1)
with bar.canvas:
BorderImage(border=(10, 10, 10, 10), pos=(bar.x, bar.center_y), size=(self.width/2, 8), source='0.png')
self.add_widget(bar)
How should I modify bar.center_y?
(1):screen shot
(2):screen shot
In the kv language, when you set an attribute like size: self.size, this attribute is automatically updated whenever the 'self' widget changes size of shape. When things are loading up in a screen/layout, they start with funky positions and sizes then move to be correct. Since things automatically update upon changing sizes/positions if you work in kv, it works as you expect.
In python, you have to explicitly bind some function to update the canvas if the size or position of the widget it's inheriting its size and pos from changes. You can do that by using the bind function (available in most/all kivy widgets). Using bind, you can say bind(<attribute>=<function>) which means anytime the widget's <attribute>, aka size or pos, is changed, it calls the <function>
I didn't test this exactly with your code since not all of it is posted, but this is what I do for my projects. Let me know how it works. If it doesn't work, edit your answer to be a snippet of code that I can copy/paste to work with and I'll update my answer.
class BarWidget(FloatLayout):
def __init__(self, **kwargs):
super(BarWidget, self).__init__(**kwargs)
self.build()
def build(self):
# Make it so you can reference the bar and border image later
self.bar = ProgressBar(pos_hint={'top':0.86,'x':0.01}, max=100, size_hint_x=0.49, size_hint_y=0.1)
with self.bar.canvas:
# Make it so you can reference the border image
self.border_image = BorderImage(border=(10, 10, 10, 10), pos=(bar.x, bar.center_y), size=(self.width, 8), source='0.png')
self.add_widget(self.bar)
# Make it so whenever the widget's pos or size changes, we update the border image
self.bar.bind(pos=self.update_border_image, size=self.update_border_image)
# make a function to update border image
def update_border_image(self, *args):
self.border_image.size = (self.width, 8) # Should this 8 be 0.8 by the way?
self.border_image.pos = (self.bar.x, self.bar.center_y)

Prevent image stretching in Kivy canvas

The situation
I've made a Widget in Kivy in order to animate an image.
<AnimatedImage>:
pos_hint: root.pos_hint
size: root.size
size_hint: .3, .3
canvas:
Rectangle:
source: 'images/image.png'
pos: self.pos[0], self.pos[1]
size: root.size[0], 435. / 770 * root.size[0]
As you can see in the last line, I used the image ratio to calculate the rectangle size.
The problem
I would like to load different images and size the widget in adjustment.
What didn't work
Using Image instead of Widget. I was not able to animate the Image size_hint using Animation object.
Thanks!

Resources