Search code examples
pythonkivykivy-language

Kivy: Absolute position and size of an image


With Kivy, how do I find both the position and size of the image?

The code below prints the position as [0,72] and the size of the image as [800, 480]. I suspect that this is the BoxLayout position and size respectively. If we use Mels image below, it's apparent that neither the position or the size is correct.

Mel

from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen

Builder.load_string("""

<MyScreenManager>:
    ThirdScreen:
        id: third_screen

<ThirdScreen>:
    name: '_third_screen_'
    id: third_screen
    BoxLayout:
        orientation: "vertical"
        id: third_screen_boxlayout
        canvas:
        Label:
            id: main_title
            text: "Title"
            size_hint: (1, 0.1)
        Image:
            id: main_image
            source: "C:/Users/OneDrive/0. T2/6. Kivy/4/claymore.jpg"
        BoxLayout:
            id: button_boxlayout
            orientation: "horizontal"
            padding: 10
            size_hint: (1, 0.15)
            Button:
                id: accept_button
                text: "Okay"
                size_hint: (0.33, 1)
                on_press: root.image_accepted_by_user(root.image_address)
            Button:
                id: crop_button
                text: "Crop"
                size_hint: (0.33, 1)
                on_press: root.enable_cropping()
            Button:
                id: cancel_button
                text: "Cancel"
                size_hint: (0.33, 1) 
                on_press: root.manager.current = '_first_screen_'
""")


class ThirdScreen(Screen, BoxLayout):
    def enable_cropping(self):
        print(self.ids.main_image.pos)
        print(self.ids.main_image.size)

# Create the screen manager
sm = ScreenManager()
sm.add_widget(ThirdScreen(name='_third_screen_'))

class MyApp(App):
    def build(self):
        return sm


if __name__ == '__main__':
    MyApp().run()

Solution

  • Absolute Position & Size

    • Absolute size, use self.ids.main_image.norm_image_size
    • Absolute pos x, use self.ids.main_image.center_x - self.ids.main_image.norm_image_size[0] / 2.
    • Absolute pos y, use self.ids.main_image.center_y - self.ids.main_image.norm_image_size[1] / 2.

    Snippet

    class ThirdScreen(Screen):
        def enable_cropping(self):
            print("\nThirdScreen:")
            print(self.ids.main_image.pos)
            print(self.ids.main_image.size)
            print("\tAbsolute size=", self.ids.main_image.norm_image_size)
            print("\tAbsolute pos_x=", self.ids.main_image.center_x - self.ids.main_image.norm_image_size[0] / 2.)
            print("\tAbsolute pos_y=", self.ids.main_image.center_y - self.ids.main_image.norm_image_size[1] / 2.)
    

    Example

    main.py

    from kivy.uix.boxlayout import BoxLayout
    from kivy.lang import Builder
    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen
    
    Builder.load_string("""
    
    <MyScreenManager>:
        ThirdScreen:
            id: third_screen
    
    <ThirdScreen>:
        name: '_third_screen_'
        id: third_screen
        BoxLayout:
            orientation: "vertical"
            id: third_screen_boxlayout
            canvas:
            Label:
                id: main_title
                text: "Title"
                size_hint: (1, 0.1)
                canvas.before:
                    Color:
                        rgba: 1, 0, 0, 1    # red
                    Rectangle:
                        pos: self.pos
                        size: self.size
            Image:
                id: main_image
                # source: "C:/Users/OneDrive/0. T2/6. Kivy/4/claymore.jpg"
                source: "./claymore.jpeg"
                canvas.before:
                    Color:
                        rgba: 0, 0, 1, 0.5    # blue
                    Rectangle:
                        pos: self.pos
                        size: self.size
            BoxLayout:
                id: button_boxlayout
                orientation: "horizontal"
                padding: 10
                size_hint: (1, 0.15)
                Button:
                    id: accept_button
                    text: "Okay"
                    size_hint: (0.33, 1)
                    on_press: root.image_accepted_by_user(root.image_address)
                Button:
                    id: crop_button
                    text: "Crop"
                    size_hint: (0.33, 1)
                    on_press: root.enable_cropping()
                Button:
                    id: cancel_button
                    text: "Cancel"
                    size_hint: (0.33, 1) 
                    on_press: root.manager.current = '_first_screen_'
    """)
    
    
    class MyScreenManager(ScreenManager):
        pass
    
    
    class ThirdScreen(Screen):
        def enable_cropping(self):
            print("\nThirdScreen:")
            print(self.ids.main_image.pos)
            print(self.ids.main_image.size)
            print("\tAbsolute size=", self.ids.main_image.norm_image_size)
            print("\tAbsolute pos_x=", self.ids.main_image.center_x - self.ids.main_image.norm_image_size[0] / 2.)
            print("\tAbsolute pos_y=", self.ids.main_image.center_y - self.ids.main_image.norm_image_size[1] / 2.)
    
    
    class MyApp(App):
        def build(self):
            return MyScreenManager()
    
    
    if __name__ == '__main__':
        MyApp().run()
    

    Output

    Img01