Toso
Toso

Reputation: 29

how to delete objects in tkinter?

I want to program a program that will draw the text where I click and when I go through it it will be deleted. This is my code when I cross the line, everything is cleared and the ones I didn't cross are drawn back. Thanks to anyone who help me.

from tkinter import *

class Program(Tk):

    def __init__(self):
        super().__init__()
        self.w, self.h = 250, 200
        self.canvas = Canvas(width=500, height=400)
        self.canvas.pack()
        self.draw_line()
        
        #self.x_lst_txt = None
        self.txt_lst_org = []
        self.txt2_lst_org = []
        self.change = False
        self.positon = False
        self.idx= 0
        self.new_lst=[]

        self.text1 = "Programovanie"
        self.text2 = "Je zábava"
        self.color1 = "green"
        self.color2 = "orange"
        self.opr1 = "-"
        self.opr2 = "+"

        self.all_binds()

    def draw_line(self):
        self.line = self.canvas.create_line(self.w, 0, self.w, self.h*2, width=5)

    def all_binds(self):
        self.canvas.bind("<Button-1>", self.draw_texts)
        self.canvas.bind("<Button-3>", self.draw_reacts)
        self.canvas.bind_all("<Right>", self.move_line_right)
        self.canvas.bind_all("<Left>", self.move_line_left)

    def draw_texts(self, event):
        self.xt = event.x
        self.yt = event.y
        uhol=self.yt

        if self.xt < self.w:
            self.text_left = self.canvas.create_text(self.xt, self.yt, text=self.text1, fill=self.color1, angle=uhol)
            self.txt2_lst_org.append([self.xt, self.yt])
            self.change = True
        else:
            self.text_right = self.canvas.create_text(self.xt, self.yt, text=self.text2, fill=self.color2, angle=-uhol)
            self.txt_lst_org.append([self.xt, self.yt])
            self.change = True

    def draw_reacts(self, event):
        self.xr = event.x
        self.yr = event.y
        
        for i in range(10):
            rect = self.canvas.create_rectangle(self.xr, self.yr+i*10, self.xr+10, self.yr+10+i*10)
            self.yr += 5

    def select_x(self, lst):
        if self.change:
            for i in range(0, len(lst)):
                if [len(i) for i in lst][self.idx] > 1:
                    self.new_lst.append(lst[i][0])
                    self.idx+=1
            self.idx = 0
            self.change=False
            return sorted(self.new_lst)
        return sorted(self.new_lst)

    def delete_all(self, lst, x_lst):
        self.new_lst = sorted(self.new_lst, reverse=self.positon)
        x_lst = sorted(x_lst, reverse=self.positon)
        del lst[0]
        del x_lst[0]
        del self.new_lst[0]

    def replace_text(self, lst, txt, fill, opr):
        for i in range(0, len(lst)+1):
            x, y = lst[i]
            angle = y
            texts = self.canvas.create_text(x, y, text=txt, fill=fill, angle=f"{opr}{angle}")


    def replace(self, lst, x_lst, con_lst, text, color, opr):
        self.delete_all(lst, x_lst)
        self.canvas.delete("all")
        self.draw_line()
        
        if lst != []:
            self.replace_text(lst, text, color, opr)

        elif con_lst != []:
            self.replace_text(con_lst, text, color, opr)


    def move_line_right(self, event):
        self.canvas.move(self.line, 5, 0)
        self.w+=5

        self.positon = False
        self.txt_lst_x = sorted(self.select_x(self.txt_lst_org))
        self.txt_lst_org = sorted(self.txt_lst_org)
        
        print("enter right",self.txt_lst_x, "org", self.txt_lst_org)

        if self.txt_lst_x != []:
            try:
                if self.w >= self.txt_lst_x[0]:
                    print("TRUE RIGHT")
                    self.replace(self.txt_lst_org, self.txt_lst_x, self.txt2_lst_org, 
                        self.text2, self.color2, self.opr1)
            except IndexError:
                pass

    def move_line_left(self, event):
        self.canvas.move(self.line, -5, 0)
        self.w-=5

        self.positon = True
        self.txt2_lst_x = sorted(self.select_x(self.txt2_lst_org), reverse=self.positon)
        self.txt2_lst_org = sorted(self.txt2_lst_org, reverse=self.positon)
        print("enter left", self.txt2_lst_x, "org", self.txt2_lst_org)

        if self.txt2_lst_x != []:
            try:
                if self.w <= self.txt2_lst_x[0]:
                    print("TRUE LEFT")
                    self.replace(self.txt2_lst_org, self.txt2_lst_x, self.txt_lst_org, 
                        self.text1, self.color1, self.opr2)
            except IndexError:
                pass

main = Program()
main.mainloop()

Upvotes: 0

Views: 494

Answers (2)

Toso
Toso

Reputation: 29

This is a full solution. If is anything complicate write me.

from tkinter import *

class Program(Tk):

def __init__(self):
    super().__init__()
    WIDTH, HEIGHT = 500, 400
    self.w=WIDTH/2
    self.canvas = Canvas(width=WIDTH, height=HEIGHT)
    self.canvas.pack()
    self.draw_line()

    self.items_text = {
        "RIGHT":[],
        "LEFT":[]
    }
    self.items_rect = {
        "RIGHT":[],
        "LEFT":[]
    }

    self.all_binds()

def draw_line(self):
    self.line = self.canvas.create_line(self.w, 0, self.w, 400, width=5)

def all_binds(self):
    self.canvas.bind("<Button-1>", self.draw_texts)
    self.canvas.bind("<Button-3>", self.draw_reacts)
    self.canvas.bind_all("<Right>", self.move_line_right)
    self.canvas.bind_all("<Left>", self.move_line_left)

def draw_texts(self, event):
    x = event.x
    y = event.y
    uhol=y

    if x < self.w:
        text_id = self.canvas.create_text(x, y, text="Programovanie", fill="green", angle=uhol)
        self.items_text["LEFT"].append({
            "id": text_id,
            "x": x
        })
    else:
        text_id = self.canvas.create_text(x, y, text="Je zábava", fill="orange", angle=-uhol)
        self.items_text["RIGHT"].append({
            "id": text_id,
            "x": x
        })

def draw_reacts(self, event):
    x = event.x
    y = event.y
    
    if x < self.w:
        for i in range(10):
            rect = self.canvas.create_rectangle(x, y+i*10, x+10, y+10+i*10)
            y += 5
            self.items_rect["LEFT"].append({
                "id": rect,
                "x": x
            })
    else:
        for i in range(10):
            rect = self.canvas.create_rectangle(x, y+i*10, x+10, y+10+i*10)
            y += 5
            self.items_rect["RIGHT"].append({
                "id": rect,
                "x": x
            })

def move_line_right(self, event):
    self.canvas.move(self.line, 5, 0)
    self.w+=5

    self.items_text["RIGHT"] = sorted(self.items_text["RIGHT"], key=(lambda item: item["x"]))
    self.items_rect["RIGHT"] = sorted(self.items_rect["RIGHT"], key=(lambda item: item["x"]))

    if self.items_text["RIGHT"]:
        first_item = self.items_text["RIGHT"][0]

        try:
            if self.w >= first_item["x"]:
                self.canvas.delete(first_item["id"])
                self.items_text["RIGHT"].pop(0)
        except IndexError:
            pass

    if self.items_rect["RIGHT"]:
        first_item = self.items_rect["RIGHT"][0]
        
        try:
            if self.w >= first_item["x"]:
                for j, i in enumerate(self.items_rect["RIGHT"]):
                    if i["x"] == first_item["x"]:
                        self.canvas.delete(i["id"])

                self.items_rect["RIGHT"] = list(filter(lambda i: i["x"] != first_item["x"], self.items_rect["RIGHT"]))

        except IndexError:
            pass

def move_line_left(self, event):
    self.canvas.move(self.line, -5, 0)
    self.w-=5

    self.items_text["LEFT"] = sorted(self.items_text["LEFT"] , key=(lambda item: item["x"]), reverse=True)
    self.items_rect["LEFT"] = sorted(self.items_rect["LEFT"], key=(lambda item: item["x"]), reverse=True)

    if self.items_text["LEFT"]:
        first_item = self.items_text["LEFT"][0]

        try:
            if self.w <= first_item["x"]:
                self.canvas.delete(first_item["id"])
                self.items_text["LEFT"].pop(0)
        except IndexError:
            pass
    
    if self.items_rect["LEFT"]:
        first_item = self.items_rect["LEFT"][0]
        
        try:
            if self.w <= first_item["x"]:
                for j, i in enumerate(self.items_rect["LEFT"]):
                    if i["x"] == first_item["x"]:
                        self.canvas.delete(i["id"])

                self.items_rect["LEFT"] = list(filter(lambda i: i["x"] != first_item["x"], self.items_rect["LEFT"]))

        except IndexError:
            pass

main = Program() main.mainloop()

Upvotes: 0

furas
furas

Reputation: 143097

I think you created too complicated code.

But first I changed names to make them more readable

        self.items_left = []
        self.items_right = []

and in similar way

        self.text_left = "Programovanie"
        self.text_right = "Je zábava"
        
        self.color_left = "green"
        self.color_right = "orange"
        
        self.opr_left = "-"
        self.opr_right = "+"

Next I keep all information as dictionary on one list

            self.items_right.append({
                'id': text_id,
                'x': x,
                'y': y,
                'angle': -angle
            })

This way I can sort all values using only one line (with key= in sorted())

 self.items_right = sorted(self.items_right, key=(lambda item: item['x']))

and I could remove function select_x()

And finally I resolved problem: I removed functions replace(), replace_text(), delete_all() and keep only three lines (but they can be reduced to two lines).

                first_item = self.items_right[0]

                # remove from canvas
                self.canvas.delete(first_item['id'])

                # remove from list
                self.items_right.pop(0)

Full working code.

from tkinter import *

class Program(Tk):

    def __init__(self):
        super().__init__()
        
        self.canvas = Canvas(width=500, height=400)
        self.canvas.pack()
        
        self.w = 250
        self.h = 200
        self.draw_line()
        
        self.items_left = []
        self.items_right = []
        
        self.change = False
        self.positon = False

        self.text_left = "Programovanie"
        self.text_right = "Je zábava"
        
        self.color_left = "green"
        self.color_right = "orange"
        
        self.opr_left = "-"
        self.opr_right = "+"

        self.set_binds()

    def draw_line(self):
        self.line = self.canvas.create_line(self.w, 0, self.w, self.h*2, width=5)

    def set_binds(self):
        self.canvas.bind("<Button-1>", self.draw_text)
        self.canvas.bind_all("<Right>", self.move_line_right)
        self.canvas.bind_all("<Left>", self.move_line_left)

    def draw_text(self, event):
        x = event.x
        y = event.y
        angle = y

        if x < self.w:
            text_id = self.canvas.create_text(x, y, text=self.text_left, fill=self.color_left, angle=angle)
            self.items_left.append({
                'id': text_id,
                'x': x,
                'y': y,
                'angle': angle
            })
        else:
            text_id = self.canvas.create_text(x, y, text=self.text_right, fill=self.color_right, angle=-angle)
            self.items_right.append({
                'id': text_id,
                'x': x,
                'y': y,
                'angle': -angle
            })
            
        self.change = True

    def move_line_right(self, event):
        self.canvas.move(self.line, 5, 0)
        self.w += 5

        self.positon = False
        self.items_right = sorted(self.items_right, key=(lambda item: item['x']))
        
        print("enter right", self.items_right)

        if self.items_right:
            #print('[DEBUG] check:', self.items_left[0], self.w) 
            first_item = self.items_right[0]
            try:
                if self.w >= first_item['x']:
                    print("TRUE RIGHT", first_item['id'])
                    #print('[DEBUG] before:', self.items_left) 
                    # remove from canvas
                    self.canvas.delete(first_item['id'])
                    # remove from list
                    self.items_right.pop(0)
                    #print('[DEBUG] after:', self.items_left) 
            except IndexError as ex:
                print('ERROR:', ex)

    def move_line_left(self, event):
        self.canvas.move(self.line, -5, 0)
        self.w -= 5

        self.positon = True
        #self.items_left = sorted(self.items_left, key=(lambda item: item['x']), reverse=True)
        self.items_left = sorted(self.items_left, key=(lambda item: -item['x']))
        
        print("enter left", self.items_left)

        if self.items_left:
            #print('[DEBUG] check:', self.items_left[0], self.w) 
            first_item = self.items_left[0]
            try:
                if self.w <= first_item['x']:
                    print("TRUE LEFT", first_item['id'])
                    #print('[DEBUG] before:', self.items_left) 
                    # remove from canvas
                    self.canvas.delete(first_item['id'])
                    # remove from list
                    self.items_left.pop(0)
                    #print('[DEBUG] after:', self.items_left) 
            except IndexError as ex:
                print('ERROR:', ex)

main = Program()
main.mainloop()

Upvotes: 1

Related Questions