【问题标题】:python/tkinter paint program undo functionpython/tkinter 绘图程序撤消功能
【发布时间】:2017-07-19 12:57:24
【问题描述】:

我尝试在我的绘图程序中添加一个撤消函数,该函数从画布中删除对象(创建的每个对象都附加到堆栈中)我试过了,它可以工作,但屏幕不会仅在第一次撤消时更新,所以如果我画 3 行然后我撤消没有任何反应,当我一次又一次撤消时,第 2 行和第 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()

【问题讨论】:

标签: python-3.x tkinter


【解决方案1】:

circle_end函数中创建圈子时,需要删除所有在圈子运动函数中创建的临时圈子

行也是如此,将其添加到您的代码中:

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_circleset_tool_lineset_tool_point 组合成一个函数,如下所示:

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

【讨论】:

  • 感谢汤姆解决了我的问题,并为不必要的发布代码感到抱歉,我对此有点陌生
  • 没问题,(只是提示:您可以按我的答案旁边的绿色勾号将其标记为正确:D)
猜你喜欢
  • 2015-08-12
  • 2013-02-03
  • 2013-01-27
  • 1970-01-01
  • 1970-01-01
  • 2015-05-19
  • 2012-11-14
  • 1970-01-01
  • 2011-04-26
相关资源
最近更新 更多