I’m writing a kivy based graph app where I can dynamically add nodes to a draw area and then connect them with directed lines(=edge). Nodes can be dragged inside the draw area and edges should stay connected to them always.
Edge class is derived from Widget class. Its graphical presentation consists of two parts, the line itself(=Line) and the tip of the line(=Triangle). When an Edge widget is drawn, its canvas is at first translated and rotated after which the tip of the edge is drawn to the canvas. After that, the canvas is rotated back to its original position and the line part is drawn to canvas.after.
When nodes are moved, the canvas of the Edge widget is cleared and the graphical presentation is drawn again. However, this doesn’t work as I planned.
If I use self.canvas.clear() at the beginning of the draw method of the Edge class, the old line is not removed and I get multiple lines on the canvas.
If I use self.canvas.after.clear() I get a completely messed up view of my draw area, since the clear method also removes the PopMatrix instruction from the canvas.after.
How can I just remove the graphical presentation of the line from the canvas.after? Is there a better way of doing this?
Kivy file of my Edge class:
<Edge>:
id: ed
size_hint: None, None
canvas.before:
Color:
rgb: 0.9, 0.1, 0.1
PushMatrix
Translate:
x: ed.translate_x
y: ed.translate_y
Rotate:
angle: ed.rot_angle
origin: ed.rot_origin_x, ed.rot_origin_y
canvas.after:
PopMatrix
UPDATE I changed my approach and now I draw everything on the canvas instead of drawing to canvas and canvas.after. Now I got the result that I wanted, but still if someone knows how to remove the individual canvas instructions it would be nice to know.
You can call it from Python using code like: class SomeWidget(Widget): def some_method(self): self. canvas. clear() with self.
canvas. before: # you can use this to add instructions rendered before with self. canvas. after: # you can use this to add instructions rendered after.
You can either:
remove a children of a canvas by doing canvas.remove()
and pass the instance of the graphics instructions you want. You can iterate and get the one with canvas.children
.
assign a group
name to a canvas property, then use canvas.remove_group()
. This is the best way to categorize and remove lot of graphics instructions without keeping a reference to them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With