How to overlay 2 layouts in Kivy (Python)?

2019-08-27 17:09发布

问题:

I am trying to make an app with a background grid and a top layer of interactive elements, I am having trouble overlaying the second layer via python, so like the title says is there a way to overlay 2 or more layouts in Kivy in ?

Here's what I am looking for

回答1:

Solution

Set the opacity of the first layer / layout to 0.5

Widget class » opacity

opacity

Opacity of the widget and all its children.

The opacity attribute controls the opacity of the widget and its children. Be careful, it’s a cumulative attribute: the value is multiplied by the current global opacity and the result is applied to the current context color.

...

opacity is a NumericProperty and defaults to 1.0.

Kivy Graphics Line » points

points: list

List of points in the format (x1, y1, x2, y2…)

Property for getting/settings points of the line

Warning

This will always reconstruct the whole graphics from the new points list. It can be very CPU expensive.

Kivy Graphics Line » circle

circle

Use this property to build a circle, without calculating the points. You can only set this property, not get it.

The argument must be a tuple of (center_x, center_y, radius, angle_start, angle_end, segments):

  • center_x and center_y represent the center of the circle
  • radius represent the radius of the circle
  • (optional) angle_start and angle_end are in degree. The default value is 0 and 360.
  • (optional) segments is the precision of the ellipse. The default value is calculated from the range between angle.

Note that it’s up to you to close the circle or not.

Example

main.py - without kv

from kivy.base import runTouchApp
from kivy.core.window import Window
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import Color, Line
from kivy.metrics import dp

Window.clearcolor = (1, 1, 1, 1)


class Overlay2Layouts(Screen):

    def __init__(self, **kwargs):
        super(Overlay2Layouts, self).__init__(**kwargs)
        self.size = Window.size

        layout1 = BoxLayout(opacity=0.5)
        with layout1.canvas:
            Color(1, 0, 0, 1)   # red colour
            Line(points=[self.center_x, self.height / 4, self.center_x, self.height * 3/4], width=dp(2))
            Line(points=[self.width * 3/ 4, self.center_y, self.width /4, self.center_y], width=dp(2))

        layout2 = BoxLayout()
        with layout2.canvas:
            Color(0, 0, 0, 1)   # black colour
            Line(circle=[self.center_x, self.center_y, 190], width=dp(2))

        self.add_widget(layout1)
        self.add_widget(layout2)


if __name__ == "__main__":
    runTouchApp(Overlay2Layouts())

main.py - using kv and Python

from kivy.lang import Builder
from kivy.base import runTouchApp
from kivy.core.window import Window

Window.clearcolor = (1, 1, 1, 1)

runTouchApp(Builder.load_string('''
#:kivy 1.11.0

Screen:
    BoxLayout:
        opacity: 0.5
        canvas.before:
            Color:
                rgba: 1, 0, 0, 1
            Line:
                width: dp(2.)
                points: [self.center_x, self.height / 4, self.center_x, self.height * 3/4]
            Line:
                width: dp(2.)
                points: [root.width * 3/ 4, self.center_y, root.width /4, self.center_y]
    BoxLayout:
        canvas.before:
            Color:
                rgba: 1, 0, 0, 1
            Line:
                width: dp(2.)
                circle: (root.center_x, root.center_y, 190)

'''))

Output



回答2:

To supplement the answer in python, the overlays didn't resize when the window changed size, so this is my solution:

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Color, Line, Ellipse, Rectangle
from kivy.metrics import dp


class RootWidget(BoxLayout):

    def __init__(self, *args, **kwargs):
        BoxLayout.__init__(self, *args, **kwargs)
        self.bind(pos=self.draw)
        self.bind(size=self.draw)
        self.layout1 = BoxLayout(opacity=0.3)
        self.layout2 = BoxLayout()
        self.add_widget(self.layout1)
        self.add_widget(self.layout2)

    def draw(self, *args):
        with self.canvas.before:
            Color(1,1,.5,1)
            self.bg = Rectangle(pos=self.pos, size=self.size)
        self.layout1.canvas.clear()
        with self.layout1.canvas:
            Color(1, 0, 0, 1)   # red colour
            Line(points=[self.center_x, self.height / 4, self.center_x, self.height * 3/4], width=dp(2))
            Line(points=[self.width * 3/ 4, self.center_y, self.width /4, self.center_y], width=dp(2))
        self.layout2.canvas.clear()
        with self.layout2.canvas:
            Color(0, 0, 0, 1)   # black colour
            Line(circle=[self.center_x, self.center_y, 190], width=dp(2))


class Overlays_3(App):
    title = "Overlays_3"

    def build(self):
        return RootWidget()


if __name__ == "__main__":
    Overlays_3().run()