gpt4 book ai didi

python - 使用 pygame 和 lambda 实现撤消和重做

转载 作者:太空宇宙 更新时间:2023-11-03 19:17:48 26 4
gpt4 key购买 nike

我正在尝试使用 lambda 在 pygame 应用程序中实现撤消和重做,但与引用有关或我对 list.remove() 实现的理解导致我的程序碰撞。创建可撤消操作的代码如下

elif MOUSEBUTTONUP == event.type:
x, y = pygame.mouse.get_pos()
if leftClick:
if len( objects ) > 0 and objects[ -1 ].is_open():
actions.do( \
[ lambda: objects[ -1 ].add( Point( x, y, 0 ) ) ], \
[ lambda: objects[ -1 ].remove( Point( x, y, 0 ) ) ] \
)
else:
actions.do( \
[ lambda: objects.append( Polygon( ( 255, 255, 255 ) ).add( Point( x, y, 0 ) ) ) ],
[ lambda: objects.pop() ] \
)

其中对象是Polygon的列表,其定义为

class Polygon:
def __init__( self, colour, width = 0 ):
self._points = []
self._colour = colour
self._isopen = True
self._width = width

def get_colour( self ):
return self._colour

def add( self, point ):
self._points.append( point )
return self

def remove( self, point ):
print "List contains " + str( self._points )
print "Trying to remove " + str( point )
self._points.remove( point )
return self

def num_points( self ):
return len( self._points )

def get_points( self ):
""" Returns a copy of the points in this vector as a list. """
return self._points[:]

def open( self ):
self._isopen = True
return self

def close( self ):
self._isopen = False
return self

def is_open( self ):
return self._isopen

def set_width( self, width ):
self._width = width
return self

def get_width( self ):
return self._width

def is_filled( self ):
return self._filled

添加的点定义为

class Point:
def __init__( self, x, y, z ):
self.x = x
self.y = y
self.z = z

def rel_to( self, point ):
x = self.move( point.z, point.x, self.z, self.x )
y = self.move( point.z, point.y, self.z, self.y )
return ( x, y )

def move( self, viewer_d, displacement, object_d, object_h ):
over = object_h * viewer_d + object_d * displacement
under = object_d + viewer_d + 1
return over / under

def __str__( self ):
return "(%d, %d, %d)" % ( self.x, self.y, self.z )

def __eq__( self, other ):
return self.x == other.x and self.y == other.y and self.z == other.z

def __ne__( self, other ):
return not ( self == other )
第一个代码段中的

actionsAction 的一个实例,其定义如下

class Actions:
#TODO implement immutability where possible
def __init__( self ):
self.undos = []
self.redos = []

def do( self, do_steps, undo_steps ):
for do_step in do_steps:
do_step()
self.undos.append( ( do_steps, undo_steps ) )
self.redos = []

def can_undo( self ):
return len( self.undos ) > 0

def undo( self ):
if self.can_undo():
action = self.undos.pop()
_, undo_steps = action
for undo_step in undo_steps:
undo_step()
self.redos.append( action )

def can_redo( self ):
return len( self.redos ) > 0

def redo( self ):
if self.can_redo():
action = self.redos.pop()
redo_steps, _ = action
for redo_step in redo_steps:
redo_step()
self.undos.append( action )

所以问题是,当我点击两次以上并尝试调用 actions.undo() 时,我遇到 list.remove(x) 异常,它说 x 不存在于列表中,我认为是因为它尝试两次删除同一点。在前两次单击之前不会发生这种情况的原因是,第一次撤消尝试删除最近的点,而第二次撤消只是将多边形从对象堆栈中弹出。我的问题是,为什么 actions.undo()Point 会尝试两次删除同一点,即使第一个点应该已从 self 中弹出。 undos 堆栈并推送到 self.redos 堆栈上?非常感谢您的任何反馈。

最佳答案

我想我已经明白了,无论如何它都能按预期工作。我推断出的理论是 lambda 操作在 x 上创建闭包。 , yz Point()的参数,因此在创建匿名函数时不是复制这些变量的值,而是维护指向它们值的指针。所以我可以删除最近的点,如 x , yz仍然引用现有点,但在第二次撤消时失败,因为该点不再存在。我使用了 stackp 的撤消/重做教程中的叶子 http://stackp.online.fr/?cat=8 ,并将参数作为列表传递给匿名函数 action.do() ,这意味着当do()时评估参数函数执行,因此正确的参数被发送到 do() 。很抱歉问题和答案很长。

关于python - 使用 pygame 和 lambda 实现撤消和重做,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10773873/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com