Python 3.x python/tkinter绘制程序撤消函数

Python 3.x python/tkinter绘制程序撤消函数,python-3.x,tkinter,Python 3.x,Tkinter,我尝试在画图程序中添加一个撤销功能,从画布上删除对象(创建的每个对象都会附加到堆栈中),我尝试了它,但屏幕不会仅在第一次撤销时更新,因此如果我画了3条线,那么我撤销什么都不会发生,当我一次又一次地撤销时,第二行和第三行将被删除,但第一行将不会被删除,直到绘制某个图形 from tkinter import * class Paint(object): DEFAULT_PEN_SIZE = 5.0 DEFAULT_COLOR = 'black' SCREEN_W=800

我尝试在画图程序中添加一个撤销功能,从画布上删除对象(创建的每个对象都会附加到堆栈中),我尝试了它,但屏幕不会仅在第一次撤销时更新,因此如果我画了3条线,那么我撤销什么都不会发生,当我一次又一次地撤销时,第二行和第三行将被删除,但第一行将不会被删除,直到绘制某个图形

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()
从tkinter导入*
类绘制(对象):
默认笔大小=5.0
默认颜色='黑色'
屏幕W=800
屏幕H=800
定义初始化(自):
self.master=Tk()
self.line\u按钮=按钮(self.master,text='line',command=self.set\u工具\u行)
self.line_按钮.grid(行=0,列=0)
self.circle\u按钮=按钮(self.master,text='circle',command=self.set\u工具\u circle)
self.circle\u button.grid(行=0,列=1)
self.point\u按钮=按钮(self.master,text='point',command=self.set\u工具\u点)
self.point\u按钮网格(行=0,列=2)
self.draw\u zone=Canvas(self.master,高度=600,宽度=600,背景为白色)
self.draw\u zone.grid(行=1,列span=5)
self.menubar=菜单(self.master)
self.menu1=菜单(self.menubar,tearoff=0)
self.menu1.add_命令(label=“Nouveau”,command=self.alert)
self.menu1.add_命令(label=“Ouvrir”,command=self.alert)
self.menu1.add_分隔符()
self.menu1.add_命令(label=“Quitter”,command=self.master.destroy)
self.menubar.add_级联(label=“Fichier”,menu=self.menu1)
self.menu2=菜单(self.menubar,tearof=0)
self.menu2.add_命令(label=“Undo”,command=self.Undo)
self.menu2.add_命令(label=“Redo”,command=self.alert)
self.menubar.add\u级联(label=“Editer”,menu=self.menu2)
self.master.config(menu=self.menubar)
self.master.title('UI')
self.setup()
self.master.mainloop()
def设置(自):
self.line\u start\u x=无
self.line\u start\u y=无
self.circle\u start\u x=无
self.circle\u start\u y=无
self.tool_选项='line'
self.Line_对象=[]
self.Circle_objects=[]
self.Point_objects=[]
self.stack=[]
self.draw\u zone.bind(“”,self.draw\u start)
自绘制区域绑定(“”,自绘制运动)
self.draw\u zone.bind(“”,self.draw\u end)
def管路_启动(自身、事件):
self.line\u start\u x=event.x
self.line\u start\u y=event.y
def管路运动(自身、事件):
self.draw\u zone.delete('temp\u line\u objects'))
self.draw\u zone.create\u line(self.line\u start\u x,self.line\u start\u y,event.x,event.y,fill=self.DEFAULT\u COLOR,smooth=1,tags='temp\u line\u objects')
def管路_端(自身、事件):
x=self.draw\u zone.create\u line(self.line\u start\u x,self.line\u start\u y,event.x,event.y,fill=self.DEFAULT\u COLOR,平滑=1)
self.Line_objects.append(x)
self.stack.append(x)
def循环_启动(自身、事件):
self.circle\u start\u x=event.x
self.circle\u start\u y=event.y
def圆周运动(自身、事件):
Douth.DrackZeal.Delphi(“TimePrCurclix Objor”)
#self.draw\u zone.create\u oval(event.x,event.y,(2*self.circle\u start\u x-event.x),(2*self.circle\u start\u y-event.y),tags='temp\u circle\u objects')
self.draw\u zone.create\u oval((self.circle\u start\u x),(self.circle\u start\u y),event.x,event.y,fill=self.DEFAULT\u COLOR,tags='temp\u circle\u objects')
def循环结束(自身、事件):
#x=self.draw\u zone.create\u oval(event.x,event.y,(2*self.circle\u start\u x-event.x),(2*self.circle\u start\u y-event.y))
x=self.draw\u zone.create\u oval((self.circle\u start\u x),(self.circle\u start\u y),event.x,event.y,fill=self.DEFAULT\u COLOR)
self.Circle\u objects.append(x)
self.stack.append(x)
def点_启动(自身、事件):
x=self.draw\u zone.create\u line(event.x,event.y,event.x+1,event.y+1)
self.Point\u objects.append(x)
def设置工具线(自):
self.tool_选项='line'
def设置工具圆(自):
self.tool_选项='circle'
def设置工具点(自身):
self.tool_选项='point'
def draw_启动(自身、事件):
如果self.tool_选项=='line':
自线路启动(事件)
elif self.tool_选项==‘圆’:
自我循环启动(事件)
elif self.tool_选项=='point':
自启动点(事件)
def draw_运动(自身、事件):
如果self.tool_选项=='line':
自我直线运动(事件)
elif self.tool_选项==‘圆’:
自我循环运动(事件)
def draw_end(自身、事件):
如果self.tool_选项=='line':
自行结束(事件)
elif self.tool_选项==‘圆’:
自我循环结束(事件)
def撤消(自我):
x=self.stack.pop()
自绘制区域删除(x)
def警报(自我):
打印('yo')
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
ge=油漆()

当您在
圆圈结束
功能中创建圆圈时,您需要删除在圆圈运动功能中创建的所有临时圆圈

行也是如此,请将以下内容添加到代码中:

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\u tool\u circle
set\u tool\u line
set\u tool\u point
组合为一个函数,如下所示:

def set_tool(self, shape):
    self.tool_option = shape

代码的缩进是混乱的,我怀疑那里的代码比复制问题所需的代码多得多。请阅读并遵循Thank Tom上的建议,感谢Tom解决了我的问题,并为不必要的张贴代码表示抱歉。我对此有点陌生。没问题,(只是一个提示:您可以按我答案旁边的绿色勾号将其标记为正确:D)