python/tkinter 绘制程序撤销功能 [英] python/tkinter paint program undo function
问题描述
我尝试在我的绘画程序中添加一个撤消功能,该功能从画布中删除对象(创建的每个对象都附加到堆栈中)画 3 行然后我撤消什么也没发生,当我一次又一次撤消时,第 2 行和第 3 行将被删除,但第一行在绘制之前不会被删除
I tried adding an undo function in my paint program which deletes objects from the canvas (every object created is appended into a stack ) I tried it, and it works but the screen does not update on only the first undo so if I draw 3 lines then I undo nothing happens, when i undo again and again the 2nd and 3rd lines will be deleted but the first one won't be deleted until a draw something
from tkinter import *
class Paint(object):
DEFAULT_PEN_SIZE = 5.0
DEFAULT_COLOR = 'black'
SCREEN_W=800
SCREEN_H=800
def __init__(self):
self.master = Tk()
self.line_button = Button(self.master, text='Line',command=self.set_tool_line)
self.line_button.grid(row=0,column=0)
self.circle_button = Button(self.master, text='Circle',command= self.set_tool_circle)
self.circle_button.grid(row=0,column=1)
self.point_button = Button(self.master, text='Point',command = self.set_tool_point)
self.point_button.grid(row=0,column=2)
self.draw_zone = Canvas(self.master,height=600,width=600,bg='white')
self.draw_zone.grid(row=1,columnspan=5)
self.menubar = Menu(self.master)
self.menu1 = Menu(self.menubar, tearoff=0)
self.menu1.add_command(label="Nouveau", command=self.alert)
self.menu1.add_command(label="Ouvrir", command=self.alert)
self.menu1.add_separator()
self.menu1.add_command(label="Quitter", command=self.master.destroy)
self.menubar.add_cascade(label="Fichier", menu=self.menu1)
self.menu2 = Menu(self.menubar, tearoff=0)
self.menu2.add_command(label="Undo", command=self.undo )
self.menu2.add_command(label="Redo", command=self.alert)
self.menubar.add_cascade(label="Editer", menu=self.menu2)
self.master.config(menu=self.menubar)
self.master.title('UI')
self.setup()
self.master.mainloop()
def setup(self):
self.line_start_x = None
self.line_start_y = None
self.circle_start_x = None
self.circle_start_y = None
self.tool_option = 'line'
self.Line_objects = []
self.Circle_objects = []
self.Point_objects = []
self.stack = []
self.draw_zone.bind('<Button-1>', self.draw_start)
self.draw_zone.bind('<B1-Motion>',self.draw_motion)
self.draw_zone.bind('<ButtonRelease-1>',self.draw_end)
def line_start(self,event):
self.line_start_x=event.x
self.line_start_y=event.y
def line_motion(self,event):
self.draw_zone.delete('temp_line_objects')
self.draw_zone.create_line(self.line_start_x,self.line_start_y,event.x,event.y,fill=self.DEFAULT_COLOR,smooth=1,tags='temp_line_objects')
def line_end(self,event):
x=self.draw_zone.create_line(self.line_start_x,self.line_start_y,event.x,event.y,fill=self.DEFAULT_COLOR,smooth=1)
self.Line_objects.append(x)
self.stack.append(x)
def circle_start(self,event):
self.circle_start_x = event.x
self.circle_start_y = event.y
def circle_motion(self,event):
self.draw_zone.delete('temp_circle_objects') #sym de circle_end par rapport a circle_start
#self.draw_zone.create_oval(event.x,event.y,(2*self.circle_start_x-event.x),(2*self.circle_start_y-event.y),tags='temp_circle_objects')
self.draw_zone.create_oval((self.circle_start_x),(self.circle_start_y),event.x,event.y,fill=self.DEFAULT_COLOR,tags='temp_circle_objects')
def circle_end(self,event):
#x=self.draw_zone.create_oval(event.x,event.y,(2*self.circle_start_x-event.x),(2*self.circle_start_y-event.y))
x=self.draw_zone.create_oval((self.circle_start_x),(self.circle_start_y),event.x,event.y,fill=self.DEFAULT_COLOR)
self.Circle_objects.append(x)
self.stack.append(x)
def point_start(self,event):
x = self.draw_zone.create_line(event.x,event.y,event.x+1,event.y+1)
self.Point_objects.append(x)
def set_tool_line(self):
self.tool_option = 'line'
def set_tool_circle(self):
self.tool_option = 'circle'
def set_tool_point(self):
self.tool_option = 'point'
def draw_start(self,event):
if self.tool_option=='line':
self.line_start(event)
elif self.tool_option == 'circle':
self.circle_start(event)
elif self.tool_option=='point':
self.point_start(event)
def draw_motion(self,event):
if self.tool_option=='line':
self.line_motion(event)
elif self.tool_option == 'circle':
self.circle_motion(event)
def draw_end(self,event):
if self.tool_option=='line':
self.line_end(event)
elif self.tool_option == 'circle':
self.circle_end(event)
def undo(self):
x = self.stack.pop()
self.draw_zone.delete(x)
def alert(self):
print('yo')
if __name__ == '__main__':
ge = Paint()
推荐答案
在circle_end
函数中创建圆的时候,需要删除所有在圆运动函数中创建的临时圆
When you create your circle in the circle_end
function, you need to delete all the temporary circles you created in the circle motion function
同样适用于行,将其添加到您的代码中:
The same goes for lines, add this to your code:
def line_end(self,event):
self.draw_zone.delete('temp_line_objects')
...
def circle_end(self,event):
self.draw_zone.delete('temp_circle_objects')
...
此外,就像 bryan Oakley 所说的那样,您的代码不需要那么长.例如,您可以将 set_tool_circle
、set_tool_line
和 set_tool_point
组合成一个这样的函数:
Also, like bryan Oakley said your code doesn't need to be as long as it is. For example you could combine set_tool_circle
, set_tool_line
and set_tool_point
into one function like this:
def set_tool(self, shape):
self.tool_option = shape
这篇关于python/tkinter 绘制程序撤销功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!