Reputation: 29
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
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
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