Обновление позиции дочерних виджетов объектов в Kivy (Python не .kv) - PullRequest
2 голосов
/ 30 марта 2019

У меня есть родительский виджет, который добавляет и размещает объекты пользовательских виджетов, но при изменении размера окна они не обновляют свою позицию ...

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


class circleChild(Widget):
    def __init__(self, *args, **kwargs):
        self.pos = kwargs.get('_pos')
        self.size = kwargs.get('_size')
        super(circleChild, self).__init__()
        with self.canvas:
            Color(0.4, 0.6, 0.9, 1)  # ConrflowerBlue
            Ellipse(pos=self.pos, size=self.size, width=dp(2))


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()
        self.layout2 = BoxLayout(opacity=0.8)
        self.add_widget(self.layout1)
        self.add_widget(self.layout2)
        self.childrenAdded = False

    def draw(self, *args):
        with self.canvas.before:
            Color(.8, .8, .8, 1)  # LightGrey
            self.bg = Rectangle(pos=self.pos, size=self.size)
        self.layout1.canvas.clear()
        with self.layout1.canvas:
            Color(0, 0, 0, 1)  # Black
            Line(
                points=[
                    self.center_x, self.center_y - 200, self.center_x,
                    self.center_y + 200
                ],
                width=dp(2))
            Line(
                points=[
                    self.center_x - 200, self.center_y, self.center_x + 200,
                    self.center_y
                ],
                width=dp(2))
        if not self.childrenAdded:
            self.addChildren()

    def addChildren(self, *args):
        circle1 = circleChild(
            _pos=[self.center_x + 100, self.center_y + 100], _size=[100, 100])
        circle2 = circleChild(
            _pos=[self.center_x + 100, self.center_y - 200], _size=[100, 100])
        circle3 = circleChild(
            _pos=[self.center_x - 200, self.center_y + 100], _size=[100, 100])
        circle4 = circleChild(
            _pos=[self.center_x - 200, self.center_y - 200], _size=[100, 100])
        self.layout2.add_widget(circle1)
        self.layout2.add_widget(circle2)
        self.layout2.add_widget(circle3)
        self.layout2.add_widget(circle4)
        self.childrenAdded = True


class PositionChildren(App):
    title = "PositionChildren"

    def build(self):
        return RootWidget()


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

Результат:

enter image description here

Проблема заключается в изменении размера окна:

enter image description here

Как бы переместить childWidgets в python?

1 Ответ

1 голос
/ 30 марта 2019

Я вижу, что вы усложняете создание новых свойств, таких как _pos или _size, вместо этого вы должны использовать только существующие свойства pos и size, с другой стороны, вы используете холст каждый раз, вместо этого повторно используя элементы.

Учитывая вышеизложенное, простое решение:

from kivy.app import App
from kivy.graphics import Color, Line, Ellipse, Rectangle
from kivy.metrics import dp
from kivy.uix.widget import Widget

class circleChild(Widget):
    def __init__(self, **kwargs):
        super(circleChild, self).__init__(**kwargs)
        self.draw()
        self.bind(pos=self.redraw, size=self.redraw)

    def draw(self):
        with self.canvas:
            Color(0.4, 0.6, 0.9, 1)  # ConrflowerBlue
            self.ellipse = Ellipse(width=dp(2))

    def redraw(self, *args):
        # reuse
        self.ellipse.pos = self.pos
        self.ellipse.size = self.size

class RootWidget(Widget):
    def __init__(self, **kwargs):
        super(RootWidget, self).__init__(**kwargs)
        self.draw()
        self.bind(pos=self.redraw, size=self.redraw)

        self.circle1 = circleChild(size=[100, 100])
        self.circle2 = circleChild(size=[100, 100])
        self.circle3 = circleChild(size=[100, 100])
        self.circle4 = circleChild(size=[100, 100])
        for c in (self.circle1, self.circle2, self.circle3, self.circle4):
            self.add_widget(c)

    def draw(self):
        with self.canvas.before:
            Color(.8, .8, .8, 1)  # LightGrey
            self.bg = Rectangle(pos=self.pos, size=self.size)
            Color(0, 0, 0, 1)  # Black
            self.vline = Line(width=dp(2))
            self.hline = Line(width=dp(2))

    def redraw(self, *args):
        # reuse
        self.bg.pos = self.pos
        self.bg.size = self.size
        self.vline.points = [
            self.center_x, 
            self.center_y - 200, 
            self.center_x,
            self.center_y + 200
        ]
        self.hline.points=[
            self.center_x - 200, 
            self.center_y, 
            self.center_x + 200,
            self.center_y
        ]
        self.circle1.pos = [self.center_x + 100, self.center_y + 100]
        self.circle2.pos = [self.center_x + 100, self.center_y - 200]
        self.circle3.pos = [self.center_x - 200, self.center_y + 100]
        self.circle4.pos = [self.center_x - 200, self.center_y - 200]

class PositionChildren(App):
    title = "PositionChildren"

    def build(self):
        return RootWidget(size=(100, 100))

if __name__ == "__main__":
    PositionChildren().run()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...