tkinter - 为什么会有像 bbox 这样的东西?

tkinter - Why is there such a thing like bbox?

现在我更多地使用 tkinter Canvas 我想知道 bbox 的使用。

对我来说,我正在使用 bbox 来获取元素的坐标,但是 Canvas 已经有一个方法来 return 一个项目的坐标。那么他们为什么要发明像 bbox 这样的东西呢?

对比tcl官方说明here:

bbox

pathName bbox tagOrId ?tagOrId tagOrId ...?

Returns a list with four elements giving an approximate bounding box for all the items named by the tagOrId arguments. The list has the form ``x1 y1 x2 y2'' such that the drawn areas of all the named elements are within the region bounded by x1 on the left, x2 on the right, y1 on the top, and y2 on the bottom. The return value may overestimate the actual bounding box by a few pixels. If no items match any of the tagOrId arguments or if the matching items have empty bounding boxes (i.e. they have nothing to display) then an empty string is returned.

坐标

pathName coords tagOrId ?coordList?

Query or modify the coordinates that define an item. If no coordinates are specified, this command returns a list whose elements are the coordinates of the item named by tagOrId. If coordinates are specified, then they replace the current coordinates for the named item. If tagOrId refers to multiple items, then the first one in the display list is used.

我看到了它们之间的区别,但无法成像,在这种情况下我需要一个 bbox 而不是坐标? 有人可以教我更好地理解这个吗?

不同之处在于,使用 bbox() 您可以获得一组项目的边界框(使用标签或 'all'),而 coords() returns 坐标具有给定标签的第一项。这是一个例子

import tkinter as tk

root = tk.Tk()
canvas = tk.Canvas(root)
canvas.pack()

i1 = canvas.create_rectangle(10, 10, 30, 50, tags='rect')
i2 = canvas.create_rectangle(60, 80, 70, 120, fill='red', tags='rect')

canvas.update_idletasks()
print('bbox', canvas.bbox('rect'))
print('coords', canvas.coords('rect'))

这给出了

bbox (9, 9, 71, 121) 
coords [10.0, 10.0, 30.0, 50.0]

bbox() 的一个典型用途是当您想使用 canvas 滚动一组小部件时: canvas 的滚动区域需要设置为包括所有canvas 内容所以 canvas.bbox('all') 非常有用。例如,参见 Adding a scrollbar to a group of widgets in Tkinter(在 onFrameConfigure() 函数中)。

理解bbox

让我们在这里使用这段代码:

import tkinter as tk

def do_bbx(event):
    item_id = event.widget.find_withtag('current')[0]
    crds = event.widget.coords(item_id)
    print(f'{item_id} was clicked')
    print(f'bbox returns, {bbx}')
    print(f'coords returns, {crds}')

root = tk.Tk()
c = tk.Canvas(root,width=250,height=250)
f = c.create_rectangle(10,20, 50, 50,
                       fill = "BLUE")
sec = c.create_rectangle(30,30, 80, 80,
                         fill = "GREEN")
bbx = c.bbox(f, sec)
c.tag_bind('all', "<Button-1>", do_bbx)

c.pack()

root.mainloop()

和运行这个return变成这个:

如果单击蓝色矩形,将打印出以下内容:

1 was clicked
bbox returns, (9, 19, 81, 81)
coords returns, [10.0, 20.0, 50.0, 50.0]

点击绿色会打印:

2 was clicked
bbox returns, (9, 19, 81, 81)
coords returns, [30.0, 30.0, 80.0, 80.0]

所以 bbox 只是安静,然后比较坐标的值,return给我们一个列表。喜欢:

import tkinter as tk

def rectangel_us(canvas, *items):
    coords = {"x1":[],"y1":[],"x2":[],"y2":[]}
    for i in items:
        coords['x1'].append(canvas.coords(i)[0])
        coords['y1'].append(canvas.coords(i)[1])
        coords['x2'].append(canvas.coords(i)[2])
        coords['y2'].append(canvas.coords(i)[3])
    x1 = min(coords['x1'])-1
    y1 = min(coords['y1'])-1
    x2 = max(coords['x2'])+1
    y2 = max(coords['y2'])+1
    return[x1,y1,x2,y2]

root = tk.Tk()
c = tk.Canvas(root,width=250,height=250)
f = c.create_rectangle(10,20, 50, 50,
                       fill = "BLUE")
sec = c.create_rectangle(30,30, 80, 80,
                         fill = "GREEN")

bbx = rectangel_us(c, f, sec)
print(bbx)


c.pack()

root.mainloop()

打印出的 bbx 将是:

[9.0, 19.0, 81.0, 81.0]

正如我们从上面知道的那样。

这可以通过这里的代码看到:

import tkinter as tk

def rectangel_us(canvas, *items):
    coords = {"x1":[],"y1":[],"x2":[],"y2":[]}
    for i in items:
        coords['x1'].append(canvas.coords(i)[0])
        coords['y1'].append(canvas.coords(i)[1])
        coords['x2'].append(canvas.coords(i)[2])
        coords['y2'].append(canvas.coords(i)[3])
    x1 = min(coords['x1'])-1
    y1 = min(coords['y1'])-1
    x2 = max(coords['x2'])+1
    y2 = max(coords['y2'])+1
    canvas.create_rectangle(x1,y1,x2,y2,
                            outline='red')

root = tk.Tk()
c = tk.Canvas(root,width=250,height=250)
f = c.create_rectangle(10,20, 50, 50,
                       fill = "BLUE")
sec = c.create_rectangle(30,30, 80, 80,
                         fill = "GREEN")

bbx = rectangel_us(c, f, sec)


c.pack()

root.mainloop()

结果是: