我创建了以下函数,允许用户将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
语句,即使它不一定是真的。 因此,在解决此问题时,非常感谢任何帮助! :)
答案 0 :(得分:1)
它发生在这里:
j = i.getfunction()
j()
如果您刚刚获得的功能是TurtleShape()
功能,那么您使用默认参数(即iop = None
)调用一次。然后,您进入大if j.__name__ == "TurtleShape":
语句并在if
块内再次调用它。
将j()
来电转移到您的else:
声明的if j.__name__ == "TurtleShape":
块中,您的问题就会消失。
这个简短的解释是否足以让您理解 为什么 问题正在发生?或者您是否需要我更深入地解释调用j()
如何使用参数TurtleShape
调用iop = None
?