在Python中使用“undo”之后的“if”语句之前执行的“else”语句

时间:2016-01-27 09:20:58

标签: python function python-3.x turtle-graphics undo

我创建了以下函数,允许用户将Python龟的形状更改为他/她从按下特定按钮时弹出的文件对话框文件对话框中选择的图像:

def TurtleShape(iop = None):
   # "iop" is supposed to be an image path
   try:
       manipulateimage.config(state = NORMAL)
       flipButton.config(state = NORMAL)
       mirrorButton.config(state = NORMAL)
       originalButton.config(state = NORMAL)
       resetturtle.config(state = NORMAL)
       rotateButton.config(state = NORMAL)
       global klob
       # The following "if-else" statement uses the "iop" argument's value as the value for "klob" if `iop` is NOT `None`
       if iop != None:
           klob = iop
           print("lmcv")
       else:
           klob = filedialog.askopenfilename()
           print("klobby")
       global im
       im = Image.open(klob)
       pictures.append(im)
       edited.clear()
       print(im)
       im.save(klob + '.gif', "GIF")
       register_shape(klob + '.gif')
       shape(klob + '.gif')
       update()
   except:
       pass

如果不是iop,上述函数也应该使用None参数的值作为乌龟的图像。

现在,考虑一下这种情况;你绘制了一堆东西,将乌龟设置为图像,就在你要打印图像时,你不小心按下了将乌龟重置为正常形状的按钮(是的,我的程序中存在该按钮) )。哦不!如果不经过所有步骤再次打开和编辑它,您将如何获得它?好吧,这就是我的undoHandler函数(如下所示)的用武之地。它只是基本上撤消了使用许多堆栈调用的最后一个函数,我将其创建为deque s。如果你精通Python,那就非常简单了:

def undoHandler():
   if len(function) > 0 and draw.drawing == True:
      undoHandler.handling = True
      if not hasattr(undoHandler, "counter"):
         undoHandler.counter = 0
      undoHandler.counter += 1
      # clear the canvas
      Clear()
      # Pop a point object from function deque
      function.pop()
      penup()
      goto(-200, 100)
      pendown()

      try:
          # Execute everything up to point before last function called
          for i in function:
             # Set canvas and turtle to previous state
             tsd = i.recieveshape()
             shape(tsd)
             mndf = i.recieveheading()
             setheading(mndf)
             hk = i.getletterheight()
             global letter_height 
             letter_height = hk
             rk = i.getletterwidth()
             global letter_width
             letter_width = rk
             milk = i.getspacewidth()
             global space_width
             space_width = milk
             hw = i.getwidth()
             width(hw)
             op = i.getcolor()
             try:
                color(op)
             except:
                for g in colors:
                   cp = g.getcolor2()
                   colormode(255)
                   color(cp)
             # Get function wrapped in Point object and execute it
             j = i.getfunction()
             j()
             # Following is the code block where the issue occurs. Basically, if the function being run is equal to `TurtleShape`, then do the following...
             if j.__name__ == "TurtleShape":
                 # `hfl` is a deque that holds all of the `pictures` deque's contents as it is cleared when the turtle is set to its default state
                 pictures.extend(hfl)
                 lmcv = pictures.pop()
                 pictures.append(lmcv)
                 try:
                     # Resize image to previous size if user changes it. Otherwise, skip this.
                     bun = picwidth.pop()
                     picwidth.append(bun)
                     mun = picheight.pop()
                     picheight.append(mun)
                     clob = lmcv.resize((int(bun), int(mun)), Image.ANTIALIAS)
                 except:
                     clob = lmcv
                 clob.save(klob + str(undoHandler.counter) + ".gif")
                 # Use the `clob.save` output from above as source image in `TurtleShape` function (this is where issue occurs)
                 TurtleShape(klob + str(undoHandler.counter) + ".gif")
                 print("Undone!")
             else:
                 pass
      except:
         pass

基本上这里发生的是它从一个队列中获取函数(包含在Point对象中),主要函数在调用它们时通过该队列。然后将函数附加到function双端队列,之后,当用户调用undoHandler时,屏幕将被清除,并从function双端队列中弹出最新值,以便所有其他行动之外的最后一个行动将再次执行。我面临的这个问题特别发生在if j.__name__ == "TurtleShape":代码块中。基本上,由于某种原因,当用户选择撤消将乌龟重置为其原始形状时,它的工作原理应该是直到由undoHandler执行TurtleShape函数。 出于某种原因,当undoHandler执行TurtleShape函数时,即使我为iop函数的TurtleShape属性提供了有效参数(正如您在{ {1}}代码块),if j.__name__ == "TurtleShape":语句首先执行 (即文件对话框出现而不是从else语句继续)。只有当用户点击该对话框中的if时,才能将乌龟设置为上一张图片。

我的代码导致出现这种情况有什么问题,以及如何阻止这种情况发生? 我尝试更改cancel属性在输出保存在klob函数中的函数中,例如undoHandler,但仍然没有运气。我还尝试在"SaveImage"中添加if-elif语句,以便在TurtleShape或文件对话框之间选择iop的值,但仍然是问题发生。显然,它会执行klob语句,即使它不一定是真的。 因此,在解决此问题时,非常感谢任何帮助! :)

1 个答案:

答案 0 :(得分:1)

它发生在这里:

         j = i.getfunction()
         j()

如果您刚刚获得的功能是TurtleShape()功能,那么您使用默认参数(即iop = None)调用一次。然后,您进入大if j.__name__ == "TurtleShape":语句并在if块内再次调用它。

j()来电转移到您的else:声明的if j.__name__ == "TurtleShape":块中,您的问题就会消失。

这个简短的解释是否足以让您理解 为什么 问题正在发生?或者您是否需要我更深入地解释调用j()如何使用参数TurtleShape调用iop = None