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:

Screenshot from 2013-10-11 23:22:15

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.

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

required