Search code examples
python-3.xuser-interfacekivykivy-language

Python Kivy - Make Ellipse adjust to available space


I'm trying to create this simple background.
This is what I have so far:

import kivy
kivy.require('1.11.1')

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout

class BaseLayout(BoxLayout):
    pass


class MyWindow(FloatLayout):
    def __init__(self, **kwargs):
        super(MyWindow, self).__init__(**kwargs)
        self.add_widget(BaseLayout())


class MyApp(App):
    # 'Global' Variables
    size_x = 220*1.3
    size_y = 250*1.3

    def build(self):
        return BaseLayout()


MyApp().run()

And my .kv-file:

#:kivy 1.11.1
#:import hex kivy.utils.get_color_from_hex

<BaseLayout>:
    orientation: "vertical"
    size: (app.size_x, app.size_y)
    size_hint: (None, None)

    #:set bg_color hex('#262626')
    #:set topBar_color hex('#1c1c1c')
    #:set bt_color hex('#4d4d4d')

    AnchorLayout:
        size_hint_y: .1

        Label:
            canvas.before:
                Color:
                    rgba: topBar_color
                Rectangle:
                    size: self.size
                    pos: self.pos

        AnchorLayout:
            anchor_x: 'right'
            anchor_y: 'center'
            padding: 10, 10

            Label:
                size_hint: (1, 1)
                # size: (25, 0)

                canvas.before:
                    Color:
                        rgba: bt_color
                    Ellipse:
                        pos: self.pos
                        size: self.size

    Label:
        size_hint_y: .9
        canvas.before:
            Color:
                rgba: bg_color
            Rectangle:
                size: self.size
                pos: self.pos

I'm looking for a way to have the circle always adapt to the height of the bar at the top (and of course it should be an actual circle and not the stretched ellipse it is now).
The window is not meant to be resized, but I want to be able to control the widget with the size_x and size_y variables, so I cannot just enter some absolute values.

The size_hint for the height is correct, but I could not find a way to just set the width of the circle to its height.

Thanks in advance


Solution

  • Here is a modified version of your kv:

    #:kivy 1.11.1
    #:import hex kivy.utils.get_color_from_hex
    
    <BaseLayout>:
        orientation: "vertical"
        size: (app.size_x, app.size_y)
        size_hint: (None, None)
    
        #:set bg_color hex('#262626')
        #:set topBar_color hex('#1c1c1c')
        #:set bt_color hex('#4d4d4d')
    
        AnchorLayout:
            anchor_x: 'right'
            size_hint_y: .1
            canvas.before:
                Color:
                    rgba: topBar_color
                Rectangle:
                    size: self.size
                    pos: self.pos
            Widget:
                size_hint: None, 1
                width: self.height
                canvas.before:
                    Color:
                        rgba: bt_color
                    Ellipse:
                        pos: self.pos
                        size: self.size
    
        Label:
            size_hint_y: .9
            canvas.before:
                Color:
                    rgba: bg_color
                Rectangle:
                    size: self.size
                    pos: self.pos
    

    This uses a Widget with size_hint: None, 1 to make it the height of the parent, and allow the width to be set as width: self.height to make a square Widget. The drawn Ellipse using that size will be a circle. Note that, in general, the AnchorLayout only works well with one child (additional children will be drawn on top of each other).