Home > Back-end >  Still not get it how to create a line on canvas when clicking on two insatnces of a class placed on
Still not get it how to create a line on canvas when clicking on two insatnces of a class placed on

Time:10-11

I am a quite beginner with tkinter. I am trying to visually connect two instances of some self created object on a canvas by clicking on them (right mouse click). In procedural coding style and using a global variable to count the clicks everything works fine. I cannot figure out what am I overlook in my code when I create everything in a class. Any clue?

from tkinter import Tk, Frame, Canvas, CURRENT, Text, END, TRUE, BOTH


class features_object():
    
    def __init__(self, master, feature_text, feature_xpos, feature_ypos, feature_color):

        self.master = master
        self.feature_text = feature_text
        self.feature_xpos = feature_xpos
        self.feature_ypos = feature_ypos
        self.feature_color = feature_color

        self.click = 0
        
        self.feature_frame = Frame(self.master, bg=self.feature_color, border=40)   
        self.feature_text = Text(self.feature_frame, font=("Helvetica", 12), relief='flat', width=20, height=3, selectbackground=self.feature_color, selectforeground="black", exportselection=TRUE)
        self.feature_text.grid(row=0, column=0, padx=5, pady=5, sticky='w')
        self.feature_text.config(wrap='word')
        self.feature_text.insert(END, feature_text)
        self.feature_tags = 'feature'
        self.feature_id = self.master.create_window(self.feature_xpos, self.feature_ypos, window=self.feature_frame, tags=self.feature_tags)


        self.bind_events()

    def bind_events(self):
        self.feature_frame.bind('<Button-1>', self.clicked)
        self.feature_frame.bind('<Button-3>', self.draw_line_with_bind)
        
    def clicked(self, event=None):
        print(f'You clicked {self.feature_id} with the cords {self.master.coords(self.feature_id)}')

    def draw_line_with_bind(self, event):
        
        self.activ_elem = self.master.coords(self.feature_id)
        
        if self.click == 0:
            self.elem_start = self.activ_elem
            self.start_x = self.activ_elem[0]
            self.start_y = self.activ_elem[1]
            self.click = 1 
        elif self.click == 1:
            self.elem_end = self.activ_elem
            self.end_x = self.activ_elem[0]
            self.end_y = self.activ_elem[1]
            self.master.create_line(self.start_x, self.start_y, self.end_x, self.end_y, fill="red", width=5)
            self.click = 0 


window = Tk()
window.geometry("1000x800")

frame_start = Frame(window)
frame_start.pack(expand=TRUE, fill=BOTH)

draw_canvas = Canvas(frame_start)
draw_canvas.pack(expand=TRUE, fill=BOTH)

created_feature_1 = features_object(draw_canvas, 'feature A', 100, 100, 'red')
created_feature_2 = features_object(draw_canvas, 'feature B', 300, 300, 'green')
created_feature_3 = features_object(draw_canvas, 'feature C', 500, 500, 'magenta')


if __name__ == '__main__':
    window.mainloop()

CodePudding user response:

  1. THis is happens because self.start_x, self.start_y, self.end_x, self.end_y, and self.count are not same for all features_objects instance.

  2. Means self.start_x, self.start_y, self.end_x, self.end_y, and self.count are different for all instances.

  3. You can use global here.


Try this.

from tkinter import Tk, Frame, Canvas, CURRENT, Text, END, TRUE, BOTH

click = 0
class features_object():
    
    def __init__(self, master, feature_text, feature_xpos, feature_ypos, feature_color):

        self.master = master
        self.feature_text = feature_text
        self.feature_xpos = feature_xpos
        self.feature_ypos = feature_ypos
        self.feature_color = feature_color

        self.click = 0
        
        self.feature_frame = Frame(self.master, bg=self.feature_color, border=40)   
        self.feature_text = Text(self.feature_frame, font=("Helvetica", 12), relief='flat', width=20, height=3, selectbackground=self.feature_color, selectforeground="black", exportselection=TRUE)
        self.feature_text.grid(row=0, column=0, padx=5, pady=5, sticky='w')
        self.feature_text.config(wrap='word')
        self.feature_text.insert(END, feature_text)
        self.feature_tags = 'feature'
        self.feature_id = self.master.create_window(self.feature_xpos, self.feature_ypos, window=self.feature_frame, tags=self.feature_tags)


        self.bind_events()

    def bind_events(self):
        self.feature_frame.bind('<Button-1>', self.clicked)
        self.feature_frame.bind('<Button-3>', self.draw_line_with_bind)
        
    def clicked(self, event=None):
        print(f'You clicked {self.feature_id} with the cords {self.master.coords(self.feature_id)}')

    def draw_line_with_bind(self, event):
        global click,start_x,start_y,end_x,end_y
        
        self.activ_elem = self.master.coords(self.feature_id)
        
        if click == 0:
            self.elem_start = self.activ_elem
            start_x = self.activ_elem[0]
            start_y = self.activ_elem[1]
            click = 1 
        elif click == 1:
            self.elem_end = self.activ_elem
            end_x = self.activ_elem[0]
            end_y = self.activ_elem[1]
            self.master.create_line(start_x, start_y, end_x, end_y, fill="red", width=5)
            print("asdkaj")
            click = 0 


window = Tk()
window.geometry("1000x800")

frame_start = Frame(window)
frame_start.pack(expand=TRUE, fill=BOTH)

draw_canvas = Canvas(frame_start)
draw_canvas.pack(expand=TRUE, fill=BOTH)

created_feature_1 = features_object(draw_canvas, 'feature A', 100, 100, 'red')
created_feature_2 = features_object(draw_canvas, 'feature B', 300, 300, 'green')
created_feature_3 = features_object(draw_canvas, 'feature C', 500, 500, 'magenta')


if __name__ == '__main__':
    window.mainloop()

Output

enter image description here

  • Related