Python 在调用.after()方法后取消事件?
我正在编写一个使用canvas小部件的PythonTkinter模块的小游戏。 有一个人,他只是一个球,和炸弹,产卵每10秒。 炸弹产生3秒后,它开始“爆炸”过程,我在self.bomb对象上调用4个以上的方法来“动画化”它爆炸 游戏的目的是试图“解除”炸弹。我想出了一些奇特的碰撞检测方法,它正在发挥作用。一旦检测到碰撞,使用以下方法将炸弹从画布上清除:Python 在调用.after()方法后取消事件?,python,events,canvas,tkinter,Python,Events,Canvas,Tkinter,我正在编写一个使用canvas小部件的PythonTkinter模块的小游戏。 有一个人,他只是一个球,和炸弹,产卵每10秒。 炸弹产生3秒后,它开始“爆炸”过程,我在self.bomb对象上调用4个以上的方法来“动画化”它爆炸 游戏的目的是试图“解除”炸弹。我想出了一些奇特的碰撞检测方法,它正在发挥作用。一旦检测到碰撞,使用以下方法将炸弹从画布上清除: self.canvas.delete(self.bomb) 然而,下面的炸弹变大和颜色改变(爆炸)的动画仍然会发生,即使我已经“解除”了炸弹
self.canvas.delete(self.bomb)
然而,下面的炸弹变大和颜色改变(爆炸)的动画仍然会发生,即使我已经“解除”了炸弹。这是因为我最初的炸弹呼吁:
self.parent.after(3000, self.explode_first)
。。。我已经链接了另外3个“explode”函数,它们都是用.after()方法绑定和调用的
我试图通过在.after()中调用的每个方法中插入条件来避免这个问题,就像布尔函数一样
if self.bomb # if there's a bomb on the canvas,
self.parent.after(125, self.explode_second) # and explode third and so on
这是行不通的。我希望能够“取消”使用after方法创建的tkinter队列中的事件,但这里是kicker。我不会(不能)消灭所有的事件,只是画布上的事件。如果可能的话,我还有其他的事情要做,我想保持原样
有办法做到这一点吗?如果没有,欢迎反馈和/或建议如何做到这一点而不取消活动后,并提前感谢
以下是相关代码,供参考:
def start_game(self):
self.Bombs += 1
self.bombsLabel.configure(text = "Total Bombs: %d" % self.Bombs)
self.b1 = random.randint(1, int(self.canvas.winfo_width()))
self.b2 = random.randint(1, int(self.canvas.winfo_height()))
self.b3 = self.b1 + 20
self.b4 = self.b2 + 20
self.create_bomb()
self.parent.after(10000, self.start_game)
以及:
您可以向正在使用的类添加一个属性,如下所示:
self.isDisarmed = False
然后将此行添加到已解除炸弹的中:
self.isDisarmed = True
然后在首先引爆中,添加一个测试以查看炸弹是否已解除武装:
def explode_first(self):
if self.bomb:
if self.isDisarmed:
self.parent.after(125, self.explode_fourth) # If bomb is disarmed, skip to the last step, where the bomb is deleted.
else: # Otherwise, carry on with bomb explosion
self.b1 -= 5
self.b2 -= 5
self.b3 += 5
self.b4 += 5
self.canvas.delete(self.bomb)
self.bomb = self.canvas.create_oval(self.b1,
self.b2,
self.b3,
self.b4,
fill = "orange")
self.parent.after(125, self.explode_second)
作为一般原则,我建议将Bomb
作为一个类,它有自己的内部属性和方法。这将更容易跟踪炸弹发生了什么,以及结果应该是什么,这将使我们有可能做一些事情,比如拥有多枚炸弹
编辑:
回复:从另一个类的方法在应用程序的画布上绘制,有一种方法:
class App:
def __init__(self, ...):
self.canvas = Tkinter.Canvas(...)
self.thingy = SomethingElse()
class SomethingElse:
def __init__(self, parentApp):
self.parentApp = parentApp
def drawSomething(self):
self.parentApp.canvas.create_oval(...)
a = App(...)
s = SomethingElse(a)
s.drawSomething()
after
方法返回表示计划事件的id。如果您保存了id,您可以在取消后调用,以取消事件:
self.after_id = self.parent.after(3000, self.explode_first)
...
self.parent.after_cancel(self.after_id)
更新:所以,我使用了canvas.find_over(self.ball):作为一个条件,这似乎有效。然而,通过查看tkinter画布的文档,这看起来很草率,如果我不解除炸弹,它将永远留在那里,就像以前一样,它们会爆炸。我完全同意第二点,(我将致力于实现和测试第一点)但我确实很难将其他对象添加到我在主类中初始化的画布中。有什么指示吗?似乎除了使用在同一个类中构建的方法之外,我无法以任何方式访问应用程序类的画布。嗯,不知道你的意思。只要将画布对象传递给另一个方法,该方法就应该能够在画布上绘制,而不管该方法属于哪个类。但无论哪种方式,让App
类的方法处理所有绘制,只需让Bomb
class“请求”就可以了它可以通过调用App
类中的方法来绘制。通常我会看到一个未定义的“画布”,或者类似的东西。我知道这不应该对自己有用。标记,但放置App.canvas.some_方法会导致内容异常。此外,我通过if not:block解决了我所看到的问题,但您的回答让我找到了它,因此我将标记为已接受,您的其他建议非常宝贵。我现在要全力以赴,添加我需要的其他类。干杯
self.after_id = self.parent.after(3000, self.explode_first)
...
self.parent.after_cancel(self.after_id)