python - Tkinter 使用 delete 从 Canvas 中删除对象

标签 python tkinter

我很难理解如何从 Canvas 中删除对象。火箭对象是从火箭类创建的,并且只是一个简单的椭圆形。事件发生后,我尝试使用 canvas.delete() 方法并将参数设置为 rocket 以便从 Canvas 中删除该对象,但它没有似乎有效。

我的目标是在列表中创建多个火箭并在动画过程中删除一些火箭。

我只包含 main() 函数。 Class Rocket 只是在 Canvas 上创建一个椭圆形并且工作正常。

file: constants.py

CANVAS_WIDTH = 600      # Width of drawing canvas in pixels
CANVAS_HEIGHT = 600     # Height of drawing canvas in pixels
ROCKET_SIZE = 30

file: test.py

import tkinter
import time
import random
from constants import *
from Rocket import Rocket

def main():
    canvas = make_canvas(CANVAS_WIDTH, CANVAS_HEIGHT, 'Fireworks')

    #put a rocket a bottom of canvas
    rocket = Rocket(canvas)
    canvas.update()
    time.sleep(50/50.)  #pause to see the rocket

    # some event occurs (not important for this example)

    canvas.delete(rocket)  #this doesn't make the rocket disappear!
    canvas.update()
    time.sleep(50/50.)

def make_canvas(width, height, title):

    top = tkinter.Tk()
    top.minsize(width=width, height=height)
    top.title(title)
    canvas = tkinter.Canvas(top, width=width + 1, height=height + 1)
    canvas.pack()
    return canvas

if __name__ == '__main__':
    main()

file: Rocket.py

import random
from constants import *

class Rocket:
    '''
    This is the blueprint for a new variable type called "Rocket"
    Every rocket has three things: an oval, a change_x and a change_y.
    Every rocket supports the "update" method which will move the rocket one step.
    '''
    def __init__(self, canvas):
        # Starting point - screen bottom with slight angle
        x_1 = random.randint(CANVAS_WIDTH/2 - 50, CANVAS_WIDTH/2 + 50)
        y_1 = CANVAS_HEIGHT - ROCKET_SIZE
        x_2 = x_1 + ROCKET_SIZE
        y_2 = CANVAS_HEIGHT
        self.fill = random.choice(['blue', 'green', 'orange', 'purple', 'red', 'lime'])
        self.oval = canvas.create_oval(x_1, y_1, x_2, y_2, fill=self.fill, outline=self.fill)
        self.change_x = random.randint(-3, 3)
        self.change_y = random.randint(-15, -5)

    # again, I pass in canvas.
    def update(self, canvas):
        # update a single rocket instance (the one given by self)
        canvas.move(self.oval, self.change_x, self.change_y)

最佳答案

当您调用canvas.delete(rocket)时, tkinter 将转换 rocket在将字符串传递给实际的删除方法之前。因此,您可以修改您的 Rocket 类以从 __str__ 返回 Canvas 对象 ID。方法:

class Rocket():
    ...
    def __str__(self):
        return str(self.oval)

这样做的缺点是它只允许您使用单个 Canvas 元素来绘制火箭。如果您有多个对象,则可以使用 __str__返回一个 id,例如“rocket#1”,并将该 id 与组成火箭的每个对象相关联。

例如,火箭使用椭圆形和方形:

def __init__(self, canvas)
    ...
    self.oval = canvas.create_oval(x_1, y_1, x_2, y_2, fill=self.fill, outline=self.fill)
    # the id of the oval to create a tag for all rocket pieces
    self.tag = f"rocket#{self.oval}"
    self.canvas.itemconfigure(self.oval, tags=(self.tag,))
    self.square = canvas.create_rectangle(x_1, y_1, x_2, y_1-20, fill="black", tags=(self.tag,))

def __str__(self):
    return self.tag

也许更好的方法是给你的火箭一个 delete方法(或 distruct!),以便它负责删除自身。

这需要保存 Canvas ,然后让火箭调用 self.canvas.delete(self.oval)当你想要摧毁火箭时。

class Rocket:
    def __init__(self, canvas):
        self.canvas = canvas
        ...

    def destruct(self):
        self.canvas.delete(self.oval)

...
def main():
    ...
    # some event occurs (not important for this example)
    rocket.destruct()

关于python - Tkinter 使用 delete 从 Canvas 中删除对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62366792/

相关文章:

python - 连接 2 个数据框并创建父子关系?

python - NET::ERR_CERT_COMMON_NAME_INVALID - 错误消息

python - 如何使 python tkinter 输出显示在 GUI 而不是 python shell 中?

Python/Tkinter 状态栏未正确更新

python - python 图像错误

python - 无法在顶级窗口中创建框架

python - 当使用 .clamp 而不是 torch.relu 时,Pytorch Autograd 会给出不同的渐变

python - SSL 不可用

python - 在Python中生成n个组合的最快方法

python - 在 Tkinter 标签中嵌入 Matplotlib 图