Kiwy drawing from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.image import Image from kivy.uix.button import Button from kivy.uix.widget import Widget from kivy.graphics import Color, Line from kivy.core.window import Window class DrawLayer(Widget): def init(self, **kwargs): super().init(**kwargs) self.strokes = [] # store all drawn lines self.current_color = (1, 0, 0) # default red self.current_width = 2 # default thickness self.drawing_enabled = False # drawing toggle def on_touch_down(self, touch): if not self.drawing_enabled: return False with self.canvas: Color(*self.current_color) new_line = Line(points=[touch.x, touch.y], width=self.current_width) self.strokes.append(new_line) return True def on_touch_move(self, touch): if self.strokes and self.drawing_enabled: self.strokes[-1].points += [touch.x, touch.y] # ========================== # UNDO LAST LINE # ========================== def undo(self): if self.strokes: last = self.strokes.pop() self.canvas.remove(last) # ========================== # CHANGE COLOR # ========================== def set_color(self, color_tuple): self.current_color = color_tuple # ========================== # CHANGE LINE WIDTH # ========================== def set_thickness(self, value): self.current_width = value class EditorUI(BoxLayout): def init(self, **kwargs): super().init(orientation="vertical", **kwargs) # Background image self.img = Image(source="graph.png", allow_stretch=True) self.add_widget(self.img) # Drawing layer above image self.draw = DrawLayer() self.add_widget(self.draw) # Toolbar toolbar = BoxLayout(size_hint_y=0.15) toolbar.add_widget(Button(text="Draw On", on_press=self.toggle_draw)) toolbar.add_widget(Button(text="Red", on_press=lambda x: self.draw.set_color((1,0,0)))) toolbar.add_widget(Button(text="Blue", on_press=lambda x: self.draw.set_color((0,0,1)))) toolbar.add_widget(Button(text="Green", on_press=lambda x: self.draw.set_color((0,1,0)))) toolbar.add_widget(Button(text="Thin", on_press=lambda x: self.draw.set_thickness(2))) toolbar.add_widget(Button(text="Thick", on_press=lambda x: self.draw.set_thickness(6))) toolbar.add_widget(Button(text="Undo", on_press=lambda x: self.draw.undo())) toolbar.add_widget(Button(text="Save", on_press=lambda x: self.save_image())) self.add_widget(toolbar) # ========================== # TOGGLE DRAWING MODE # ========================== def toggle_draw(self, btn): self.draw.drawing_enabled = not self.draw.drawing_enabled btn.text = "Draw Off" if self.draw.drawing_enabled else "Draw On" # ========================== # SAVE MERGED IMAGE # ========================== def save_image(self): self.export_to_png("edited_graph.png") print("Saved as edited_graph.png") class AnnotatorApp(App): def build(self): return EditorUI() AnnotatorApp().run()