Python 在调用.after()方法后取消事件?

Python 在调用.after()方法后取消事件?,python,events,canvas,tkinter,Python,Events,Canvas,Tkinter,我正在编写一个使用canvas小部件的PythonTkinter模块的小游戏。 有一个人,他只是一个球,和炸弹,产卵每10秒。 炸弹产生3秒后,它开始“爆炸”过程,我在self.bomb对象上调用4个以上的方法来“动画化”它爆炸 游戏的目的是试图“解除”炸弹。我想出了一些奇特的碰撞检测方法,它正在发挥作用。一旦检测到碰撞,使用以下方法将炸弹从画布上清除: self.canvas.delete(self.bomb) 然而,下面的炸弹变大和颜色改变(爆炸)的动画仍然会发生,即使我已经“解除”了炸弹

我正在编写一个使用canvas小部件的PythonTkinter模块的小游戏。 有一个人,他只是一个球,和炸弹,产卵每10秒。 炸弹产生3秒后,它开始“爆炸”过程,我在self.bomb对象上调用4个以上的方法来“动画化”它爆炸

游戏的目的是试图“解除”炸弹。我想出了一些奇特的碰撞检测方法,它正在发挥作用。一旦检测到碰撞,使用以下方法将炸弹从画布上清除:

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)