that doesn't make any sense…
… can you repeat it again?

Author Archives: tototico
Kivy: Interactive Applications in Python – E-book for $5
to_parent and to_widget methods in Kivy
In my previous post, I explained the use of to_window
and to_widget
property as a way of transforming relative coordinates to absolute coordinates. In this post I will explain how do we transform coordinates between a particular widget and its parent. Basically, we just need to use the to_parent
and to_local
methods instead. However, these methods causes much more confusion than the transformation into absolute coordinates.
Let’s work with exactly the same example of the previous post. Following is the Kivy language code.
<RelativeLayout>: pos: 100,100 size_hint: .6,.6 canvas: Line: rectangle: 0,0, self.width, self.height <Relatives>: RelativeLayout: Button: pos: 0,0 size_hint: .4,.3 text: "Press Me!" on_press: text = root.test(*args)
Here is the output of that code:
And following is the Python code, in which we just changed the to_window
and to_widget
methods for to_parent
and to_local
respectively.
from kivy.app import App from kivy.uix.relativelayout import RelativeLayout class Relatives (RelativeLayout): def test(self, inst): print "inst.pos = " + str(inst.pos) to_parent = inst.to_parent(*inst.pos) print "to_parent = " + str(to_parent) to_local = inst.to_local(*to_parent) print "to_local = " + str(to_local) class RelativesApp(App): def build(self): return Relatives() RelativesApp().run()
When we press the Button
instance, we get the following output in the terminal.
inst.pos = [0, 0] to_parent = (0, 0) to_local = (0, 0)
It seems like it didn’t work because the to_parent
output is the same. Why? Let’s give this a second thought. The coordinate inst.pos
is the position where the Button
instance is located relative to its parent. So, we already have a coordinate relative to its parent. When we call on the to_parent
method, we are actually requesting the coordinate on the same coordinate system.
Most of the time, what we probably want is obtaining the coordinate on the parent’s coordinate system. So instead on calling on inst.to_parent
, we should call on the inst.parent.to_parent
. Equivalently, we need to call on inst.parent.to_local
, instead of just inst.to_local
. The following code contains the correction.
from kivy.app import App from kivy.uix.relativelayout import RelativeLayout class Relatives (RelativeLayout): def test(self, inst): print "inst.pos = " + str(inst.pos) to_parent = inst.parent.to_parent(*inst.pos) print "to_parent = " + str(to_parent) to_local = inst.parent.to_local(*to_parent) print "to_local = " + str(to_local) class RelativesApp(App): def build(self): return Relatives() RelativesApp().run()
And here is the output.
inst.pos = [0, 0] to_parent = (100, 100) to_local = (0, 0)
Now, we are getting coordinates relative to Relatives
as you might be expecting.
Just to make sure you understand, please try the following exercise. For the above example, would the statement print str(inst.parent.parent.to_parent(*inst.pos))
print the same terminal output as print str(inst.to_window(*inst.pos))
?
Think about it before read the answer.
Answer: Since we are sending the coordinate (0, 0) directly as parameter to the Relatives
instance without a way to specify that it initially belong to the Button
instance, then the answer is no. In fact, in this particular case, the output is exactly the same.
Maybe it is clearer if I you just check the following code which is the real equivalent to print str(inst.to_window(*inst.pos))
.
to_parent = inst.parent.to_parent(*inst.pos) print inst.parent.parent.to_parent(*to_parent)
As you can see, there are two steps to get to the absolute coordinates traversing the relative layouts. Of course, this just apply to this particular example of two relative layouts.
Comic #7 – Demographics and Marketing Strategy
to_window and to_local methods in Kivy
One common confusion in Kivy is the correct distinction between to_window
, to_widget
, to_local
and to_parent
methods. In this post I will focus in to_window
and to_widget
methods.
Kivy usually works with absolute coordinates, i.e. no matter where you are trying to position a Widget
, the origin coordinate (0,0) will always be at the bottom-left corner of your window.
Please notice that this post applies specifically to the absolute position properties (pos
, x
, y
, top
, bottom
), not to the proportional position property (pos_hint
property) .
Apart from the pos_hint
property, there are some exceptions where Kivy stops using absolute coordinates. For example, when we are directly inside a RelativeLayout
or Scatter
. In this cases, we might need to convert coordinates relative to the Widget
to absolute Window
coordinates, or vice-versa.
A common situation in which we need to do this is when we are receiving touch events. Let’s study an example. Here is the Kivy code:
<RelativeLayout>: pos: 100,100 size_hint: .6,.6 canvas: Line: rectangle: 0,0, self.width, self.height <Relatives>: RelativeLayout: Button: pos: 0,0 size_hint: .4,.3 text: "Press Me!" on_press: text = root.test(*args)
What we have is a Button
inside a RelativeLayout
inside Relatives
. A Relatives
instance will be the the main Widget
of the Window
, and therefore it will share its absolute coordinates. Here is a screenshot of the example:
The following is the Python code which is going to print the coordinates of to_window
and to_widget
in the test
method:
import kivy kivy.require('1.7.0') from kivy.app import App from kivy.uix.relativelayout import RelativeLayout class Relatives (RelativeLayout): def test(self, inst): print "inst.pos = " + str(inst.pos) to_window = inst.to_window(*inst.pos) print "to_window = " + str(to_window) to_widget = inst.to_widget(*to_window) print "to_widget = " + str(to_widget) class RelativesApp(App): def build(self): return Relatives() RelativesApp().run()
This is the output of the program:
inst.pos = [0, 0] to_window = (200, 200) to_widget = (0, 0)
The initial position of the Button
is (0,0), relative to the RelativeLayout
. When to_window
is called on, the relative coordinate is transformed into an absolute one (200,200). The Button
is inside two RelativeLayouts
instances. Each of one is at the position (100,100). Relatives
is at (100,100) of the Window
and the insider RelativeLayout
is at (100,100) of the Relatives
instance. Therefore the Button
is at (200,200) of the Window
. The coordinate is restored calling the to_widget
method.
The to_window
method will always return absolute coordinates relative to the Window
, no matter how many RelativeLayout
(or Scatter
) instances are in the middle. In other words, if there are several RelativeLayout
instances embedded into each other, the method will traverse them until it gets the coordinates in the Window
.
I will be posting about to_parent
and to_local
methods very soon.