KIVY изменить размер виджета на основе другой позиции виджета - PullRequest
0 голосов
/ 18 апреля 2020

У меня есть горизонтальная (hLine) и вертикальная линия (vLine) в Relativelayout. Горизонтальная линия будет просто касаться вертикальной линии. Когда я перемещаю вертикальную линию, как динамически изменять ширину горизонтальных линий (т.е. горизонтальная линия будет растягиваться, а не двигаться) так, чтобы она просто касалась вертикальной линии. Любая идея, пожалуйста. В приведенном ниже примере предполагается, что вертикальная линия просто прокручивается слева направо и наоборот (т.е. она перемещается горизонтально). Для примера я предоставил только одну горизонтальную линию. В моем реальном проекте будет как минимум 10 горизонтальных линий, соприкасающихся с вертикальной.

from kivy.app import App
from kivy.graphics import Line, Color
from kivy.uix.scatter import Scatter
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.core.window import Window

class MyPaintApp(App):

    def build(self):
        root = RelativeLayout()

        (ix, iy) = (100,100)
        (fx, fy) = (200,100)

        clr = Color(0.2, 0.2, 1)

        wdgt1 = Scatter(pos = (ix,iy), size = (fx-ix, 5))
        (ix,iy) = wdgt1.to_local(ix,iy,relative=True)
        (fx,fy) = wdgt1.to_local(fx, fy,relative=True)
        hLine = Line(points=[ix,iy, fx, fy], width=2, cap='none')
        lbl = Label(text='[color=3333ff]Horizontal[/color]', markup = True, pos=(ix,iy ))
        wdgt1.canvas.add(clr)
        wdgt1.canvas.add(hLine)
        wdgt1.add_widget(lbl)

        (fx, fy) = (200,150)
        (dx, dy) = (200,50)

        wdgt2 = Scatter(pos = (fx,fy), size = (5, fy - dy))
        (fx,fy) = wdgt2.to_local(fx, fy,relative=True)
        (dx,dy) = wdgt2.to_local(dx,dy,relative=True)
        vLine = Line(points=[fx,fy, dx, dy], width=2, cap='none')
        lbl = Label(text='[color=3333ff]Vertical[/color]', markup = True, pos=(fx,fy ))
        wdgt2.canvas.add(clr)
        wdgt2.canvas.add(vLine)
        wdgt2.add_widget(lbl)





        root.add_widget(wdgt1)
        root.add_widget(wdgt2)

        return root

if __name__ == '__main__':
    Window.clearcolor = (1, 1, 1, 1)
    MyPaintApp().run()

1 Ответ

1 голос
/ 19 апреля 2020

Вы можете сделать это, перерисовав Canvas из wdgt1 всякий раз, когда wdgt2 перемещается. Вот модифицированная версия вашего кода, которая делает это:

from kivy.app import App
from kivy.graphics import Line, Color
from kivy.uix.scatter import Scatter
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.label import Label
from kivy.core.window import Window

class MyPaintApp(App):
    def __init__(self, **kwargs):
        super(MyPaintApp, self).__init__(**kwargs)
        self.hLine = None

    def build(self):
        root = RelativeLayout()

        (ix, iy) = (100,100)
        (fx, fy) = (200,100)

        self.clr = Color(0.2, 0.2, 1)

        self.wdgt1 = Scatter(pos = (ix,iy), size = (fx-ix, 5))
        (ix,iy) = self.wdgt1.to_local(ix,iy,relative=True)
        (fx,fy) = self.wdgt1.to_local(fx, fy,relative=True)
        self.hLine = Line(points=[ix,iy, fx, fy], width=2, cap='none')
        self.lbl = Label(text='[color=3333ff]Horizontal[/color]', markup = True, pos=(ix,iy ))
        self.wdgt1.canvas.add(self.clr)
        self.wdgt1.canvas.add(self.hLine)
        self.wdgt1.add_widget(self.lbl)

        (fx, fy) = (200,150)
        (dx, dy) = (200,50)

        wdgt2 = Scatter(pos = (fx,fy), size = (5, fy - dy))
        (fx,fy) = wdgt2.to_local(fx, fy,relative=True)
        (dx,dy) = wdgt2.to_local(dx,dy,relative=True)
        vLine = Line(points=[fx,fy, dx, dy], width=2, cap='none')
        lbl = Label(text='[color=3333ff]Vertical[/color]', markup = True, pos=(fx,fy ))
        wdgt2.canvas.add(self.clr)
        wdgt2.canvas.add(vLine)
        wdgt2.add_widget(lbl)

        wdgt2.bind(pos=self.move_wdgt2)  # bind to movement of wdgt2

        root.add_widget(self.wdgt1)
        root.add_widget(wdgt2)

        return root

    def move_wdgt2(self, wdgt2, new_pos):
        if self.hLine is None:
            return

        # calculate the new ending x coordinate of the hLine
        x1, y1 = self.wdgt1.to_local(wdgt2.x, wdgt2.y, relative=True)
        pts = self.hLine.points
        pts[2] = x1

        # recreate the hLine
        self.hLine = Line(points=pts, width=2, cap='none')

        # clear the canvas
        self.wdgt1.canvas.clear()
        self.wdgt1.remove_widget(self.lbl)

        # redraw the canvas
        self.wdgt1.canvas.add(self.clr)
        self.wdgt1.canvas.add(self.hLine)
        self.wdgt1.add_widget(self.lbl)


if __name__ == '__main__':
    Window.clearcolor = (1, 1, 1, 1)
    MyPaintApp().run()
...