【问题标题】:finding widgets in a canvas by their handles通过句柄在画布中查找小部件
【发布时间】:2020-05-21 07:04:26
【问题描述】:

我想通过手柄找到一些放在画布上的矩形。例如,如果我在一个系列中有 5 个矩形位置并且它们的句柄范围从 25 到 30,我想通过它们的句柄找到矩形并删除矩形。

到目前为止,我已经看到使用标签来查找矩形(或画布上的项目)的方法,但标签对我不起作用,因为我将所有矩形都放在一个循环中,而且似乎只有最后一个标签是与矩形相关联。而且由于我可以使用标签之类的句柄来唯一标识矩形,我想知道是否可以在给定范围的情况下找到它们?

感谢您的帮助

【问题讨论】:

  • 不知道为什么不能使用标签。实际上标签更方便,因为它可以引用一组您需要的项目。
  • 给定范围?Edit您的问题并详细解释一下?阅读Tkinter.Canvas.find_*-method's

标签: python tkinter tkinter-canvas


【解决方案1】:

tkinter Canvas 不是完全面向对象的,也就是说,您不能开箱即用地直接在项目上调用画布项目上的方法;您必须调用将找到该项目的画布对象上的方法,并修改其属性。这是通过项目 ID 或标签完成的。

但是,您可以创建一个 OOP 层来允许您正在寻找的行为:在以下示例中,class CanvasObject 将画布项包装在一个可以调用的对象中。您必须包装您希望调用的画布方法,以启用完整的行为。

该示例展示了如何使用Canvas.itemconfig 方法来执行此操作。

import tkinter as tk


class CanvasObject:
    id = 0
    def __init__(self, canvas, canvas_id):
        self.canvas = canvas          # keep a reference of the canvas
        self.canvas_id = canvas_id    # keep a reference of the item id on the canvas
        self.id = CanvasObject.id            # each CanvasObject has its own unique id
        CanvasObject.id += 1
        
    def itemconfig(self, **kwargs):
        self.canvas.itemconfig(self.canvas_id, kwargs)

        
root = tk.Tk()
canvas = tk.Canvas(root)
canvas.pack(expand=True, fill=tk.BOTH)

# create a CanvasObject from the canvas item
rec = CanvasObject(canvas, canvas.create_rectangle((10, 10), (50, 40), fill='', outline='black'))

# dot notation call is now possible directly on the CanvasObject
rec.itemconfig(fill='red', outline='blue')   

root.mainloop()

【讨论】:

    【解决方案2】:

    因为我可以使用标签之类的句柄来唯一标识矩形...

    那不是真的。如果你有画布项目的句柄,那么你不需要找到它们。您可以直接使用句柄,假设“句柄”是指创建项目时返回的唯一标识符。

    这是一个人为的示例,它创建了 100 个随机颜色的矩形。它保存所有绿色项目的句柄,并提供一个按钮,单击该按钮将删除绿色项目。

    import tkinter as tk
    import random
    
    root = tk.Tk()
    canvas = tk.Canvas(root, width=400, height=400, bg="black")
    canvas.pack(fill="both", expand=True)
    green_items = []
    for i in range(100):
        x = random.randint(10, 390)
        y = random.randint(10, 390)
        fill = random.choice(["red", "green", "blue", "yellow"])
        item_id = canvas.create_rectangle(x,y, x+10, y+10, fill=fill)
        if fill == "green":
            green_items.append(item_id)
    
    def delete_green():
        for item_id in green_items:
            canvas.delete(item_id)
    
    button = tk.Button(root, text="Delete Green", command=delete_green)
    button.pack()
    root.mainloop()
    

    【讨论】:

    • 感谢您的澄清,这似乎是一种更简单的方法。为了澄清我的意思:画布上的每个项目都有一个唯一的项目句柄,它是一个整数值,所以如果我有 20 个项目,句柄的范围是 1 到 20。但如果我想特别删除其中一组,我可以做到的一种方法是提供一个单独的标签,如下所示: canvas.itemconfig(item, tags="del") in a loop ,然后使用这个标签找到它们并删除它们。
    • @rkm19:如果您有句柄,则无需循环它们,添加标签,然后删除,当您可以循环它们并删除时。但是,是的,您可以遍历它们并添加标签。然后,您不需要使用标签来“找到它们”,只需在单个删除命令中使用标签即可。
    猜你喜欢
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多