KJG
KJG

Reputation: 113

KIVY change widget size based on another widget position

I have a horizontal (hLine) and Vertical Line (vLine) in Relativelayout. Horizontal line will be just touching Vertical Line. When I move Vertical Line, how to dynamically change Horizontal lines width (i.e horizontal line will stretch instead of moving ) so that it just touches Vertical Line. Any idea please. In given example below presume that Vertical line just scrolls left to right and vice versa (i.e it moves horizontally). For sample I had provided only one horizontal line. In my actual project there will be atleast 10 Horizontal lines touching the vertical line.

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()

Upvotes: 0

Views: 93

Answers (1)

John Anderson
John Anderson

Reputation: 38837

You can do that by redrawing the Canvas of wdgt1 whenever wdgt2 moves. Here is a modified version of your code that does that:

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()

Upvotes: 1

Related Questions