Search code examples
pythonkivydraw

How to draw line in each widget in Python Kivy


I'm trying to show binary tree on labels. How can I draw lines inside each label from the center to the right and left edges? The task is very strange, I understand, but you i need to display a self-written tree with the most basic Kivy objects. Kivy trees cannot be used. All solutions on the Internet are only for the touchscreen.

In this loop i add labels with node value, if node is not found it is 0

class TreeApp(App):
    def build(self):
        bl = BoxLayout(orientation='vertical', padding=5, spacing=5)
            for i in range(maxdepth):
                inside_bl = BoxLayout(orientation='horizontal')
                for j in range(2 ** i):
                    try: inside_bl.add_widget(Label01(text=str(mx_lvl[i][j]),color=(0.5,0.5,0.5,1)))
                    except: inside_bl.add_widget(Label111(text="0",color=(0.5,0.5,0.5,0.5)))
                bl.add_widget(inside_bl)
        return bl

Here i tried to make class label01. I thought using self. will create its own line for each label and draw relative to the origin or center of the label.

class Label01(Label):
    def __init__(self,**kwargs):
        super(Label01,self).__init__(**kwargs)

        with self.canvas:
            self.pos = self.pos
            Color(0,1,0,1)
            self.line= Line(points=(self.x+100,self.y+100,self.x+250,self.y+250),close = True)

Likewise for label 111. I thought using self. will create its own unique line for each label and draw relative to the origin or center of the label.

  • tree.kv
#:kivy 1.11.1
<Label111>:
    canvas.before:
        Line:
            
            width: 2
            points: (self.x, self.y+50, self.x+200, self.y+100, self.x+300, self.y+200)
        Color:
            rgb: (0.9,0.9,0.9,0.9)
  • main.py:
class Label111(Label):
    pass

I thought that when using self. i will get a test line inside each label (31 in total) but i got only 2 lines at the bottom of the window. Question: How do I draw two lines inside each label relative to its center? Window with only two lines


Solution

  • Because you are drawing the lines for Label01 in its __init__() method, all the lines are drawn before the position and size of the Label01 are set. So all the lines are drawn using the default position of the Label01, which is (0,0). Since you are doing this in the python code, there is no binding to adjust the lines when the position of the Label01 is changed.

    This can be fixed by either writing your own bindings to do the adjustments, or by letting kv do it for you by defining the lines in kv. Like this:

    <Label01>:
        canvas.before:
            Color:
                rgba: 0,1,0,1
            Line:
                points: self.center_x,self.center_y,self.center_x+250,self.center_y+250
    

    The points are defined relative to the center of the Label01 (as you mentioned), and then the definition for Label01 becomes simply:

    class Label01(Label):
        pass