Jacob French
Jacob French

Reputation: 21

How to get widget position in kivy

I am learning to code with Python and Kivy. I want to get the position of a button (button1), which is in a boxlayout, relative to the window. However when I print button1.pos or button1.to_window(*button1.pos) I get [0, 0] which is clearly not the position of the button. I am assuming that the button position has not yet been changed at the time that I get the position but i'm not sure from where I can put this code so that it is executed after the button position has been changed (presumably by the layout), If this is the issue at all.

As you can see in my code, I tried to get the position from the on_start method, hoping this would solve my problem, but I got the same result.

Here is my code:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button

class Example(App):
    def build(self):
        return root

    def on_start(self):
        print("Position: " + str(button1.pos))
        print("Position2: " + str(button1.to_window(*button1.pos)))

root = BoxLayout()
root.orientation = 'vertical'
button1 = Button(text = "Button1")
button2 = Button(text = "Button2")
root.add_widget(button1)
root.add_widget(button2)

Example().run()

Thanks

Upvotes: 2

Views: 3511

Answers (1)

eyllanesc
eyllanesc

Reputation: 243887

To understand the problem you should review the docs:

on_start()

Event handler for the on_start event which is fired after initialization (after build() has been called) but before the application has started running.

As noted start() is called before starting the application so the BoxLayout still does not do its job so you will get the default position of every widget that is (0, 0). For these cases you must use Clock.schedule_once() that calls the function when it finishes executing the synchronous task and the next frame is rendered.

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.clock import Clock

class Example(App):
    def build(self):
        Clock.schedule_once(lambda *args: self.print_pos())
        return root

    def print_pos(self):
        print("Position: " + str(button1.pos))
        print("Position2: " + str(button1.to_window(*button1.pos)))

root = BoxLayout()
root.orientation = 'vertical'
button1 = Button(text = "Button1")
button2 = Button(text = "Button2")
root.add_widget(button1)
root.add_widget(button2)

Example().run()

In my case I get the following:

Position: [0, 300.0]
Position2: (0, 300.0)

And that is valid since the position in kivy is with respect to the bottom left.

Upvotes: 1

Related Questions