Python tkinter 删除 event.widget.create_line
我写了一个简单的画图程序,但在做一项任务时遇到了问题。我想要能够删除已经画出的线条。当按下鼠标左键(ButtonPress-1)时,会一直画出一条线,直到松开鼠标左键(ButtonRelease-1)。而当我按下“重置”按钮时,我希望能删除这条线。目前我设置的是,当我按下“重置”时,程序会重新启动,这样的解决办法并不好。
from Tkinter import *
import tkMessageBox
import sys
import os
import subprocess
b1 = "up"
xold, yold = None, None
color= "black"
linesize = 2
def main():
global root
root = Tk()
global drawing_area
drawing_area = Canvas(root, width=1050, height=1200, background="white")
drawing_area.pack()
drawing_area.bind("<Motion>", motion)
drawing_area.bind("<ButtonPress-1>", b1down)
drawing_area.bind("<ButtonRelease-1>", b1up)
button1 = Button(root, text = "Reset", command = restart_program, anchor = N)
button1.configure(width = 3, background = "#FFFFFF", relief = FLAT)
button1_window = drawing_area.create_window(640, 0, anchor=N, window=button1)
root.geometry('1050x1200')
root.geometry('+0+720')
root.mainloop()
def restart_program():
python = sys.executable
os.execl(python, python, * sys.argv)
def b1down(event):
global b1
b1 = "down"
def b1up(event):
global b1, xold, yold
b1 = "up"
xold = None
yold = None
def motion(event):
if b1 == "down":
global xold, yold
if xold is not None and yold is not None:
event.widget.create_line(xold,yold,event.x,event.y,smooth=TRUE,fill = color, width=linesize)
xold = event.x
yold = event.y
if __name__ == "__main__":
main()
1 个回答
4
如果你想删除画布上的所有物品,可以使用canvas.delete("all")这个命令。
或者,你可以给画的线条加个标签,然后通过标签来删除。
所以你可以把:
event.widget.create_line(xold,yold,event.x,event.y,smooth=TRUE,fill = color, width=linesize)
改成:
event.widget.create_line(xold,yold,event.x,event.y,smooth=TRUE,fill = color, width=linesize, tag="line")
然后调用:
canvas.delete("line")这样就会删除所有带有这个标签的物品。
补充说明:
为了满足最初的请求,这里有一个代码示例,可以实现简单的撤销和重做功能,但请注意以下几个缺点:
- 当你撤销更多的物品时,存储的列表会不断增长,没有大小限制。
如果你撤销了一个物品,然后手动画了一个新物品,重做时仍然会把被删除的线条放回去。
import Tkinter as tk import tkMessageBox import sys import os class App(tk.Tk): b1 = "up" xold, yold = None, None color= "black" linesize = 2 counter = 1 #keeps track of the current working line, is incremented as soon as line is finished undone = [] #keeps a list of coordinate lists on undone items def __init__(self): tk.Tk.__init__(self) self.drawing_area = tk.Canvas(self, width=600, height=600, background="white") self.drawing_area.pack() self.drawing_area.bind("<Motion>", self.motion) self.drawing_area.bind("<ButtonPress-1>", self.b1down) self.drawing_area.bind("<ButtonRelease-1>", self.b1up) self.button1 = tk.Button(self, text = "Reset", command = self.blank_canvas, anchor = tk.N) self.button1.configure(width = 3, background = "#FFFFFF", relief = tk.FLAT) self.button1.pack(side="left") self.button2 = tk.Button(self, text = "Undo", command = self.undo, anchor = tk.N) self.button2.configure(width = 3, background = "#FFFFFF", relief = tk.FLAT) self.button2.pack(side="left") self.button3 = tk.Button(self, text = "Redo", command = self.redo, anchor = tk.N) self.button3.configure(width = 3, background = "#FFFFFF", relief = tk.FLAT) self.button3.pack(side="left") def blank_canvas(self): self.drawing_area.delete("line") def undo(self): self.counter -= 1 #decrements the counter to look at the previous item currentlist = [] #creates a list to store the coordinates in for item in self.drawing_area.find_withtag("line"+str(self.counter)): #find all sub lines from the previous line currentlist.append(self.drawing_area.coords(item)) #get and add the coordinates to the working list self.drawing_area.delete("line"+str(self.counter)) #delete all items of the current line self.undone.append(currentlist) #add the working list to the stored list def redo(self): try: currentlist = self.undone.pop() #fetch and remove last set of coordinates for coords in currentlist: #for set of coordinates redraw subline self.drawing_area.create_line(coords,smooth=tk.TRUE,fill = self.color, width=self.linesize, tags=["line", "line"+str(self.counter)]) self.counter += 1 #re increment counter except IndexError: pass #occurs if list is empty def b1down(self, event): self.b1 = "down" def b1up(self, event): self.b1 = "up" self.xold = None self.yold = None self.counter += 1 def motion(self, event): if self.b1 == "down": if self.xold is not None and self.yold is not None: event.widget.create_line(self.xold,self.yold,event.x,event.y,smooth=tk.TRUE,fill = self.color, width=self.linesize, tags=["line", "line"+str(self.counter)]) self.xold = event.x self.yold = event.y if __name__ == "__main__": app = App() app.mainloop()