Python 在坐标处找不到 tkinter 项目

Python can't find tkinter item at coordinates

我有这个代码:

for item in items:
    print ( "Item: ", item, mycanvas.coords (item) )

print ("Item at 26.0, 188.0 ", mycanvas.find_closest(26.0, 188.0))
print ("Item at 998.0, 594.0 ", mycanvas.find_closest(998.0, 594.0))

当我 运行 它时,我得到:

('Item: ', 1, [985.0, 565.0])
('Item: ', 8, [25.0, 25.0])
('Item: ', 15, [505.0, 25.0])
('Item: ', 28, [1362.0, 31.0])
('Item: ', 35, [1020.0, 119.0])
('Item: ', 42, [1050.0, 583.0])
('Item: ', 49, [25.0, 25.0])
('Item: ', 56, [26.0, 188.0])
('Item: ', 63, [998.0, 594.0])
('Item: ', 70, [1152.0, 38.0])
('Item at 26.0, 188.0 ', (57,))
('Item at 998.0, 594.0 ', (64,))

最后两行应分别读取找到的项目 5663

我的屏幕上有 10 张图片,我想找出点击的是哪一张。更糟糕的是,X、Y 坐标被传递给屏幕位置而不是 canvas 位置,我将不得不弄清楚如何转换:

def popup(event):
    x = mycanvas.canvasx(event.x_root)
    y = mycanvas.canvasy(event.y_root)
    print( "Adjusted x, y: ", x, y )
    FoundItem=mycanvas.find_closest(x, y)
    print( "Found Item @ x, y: ", FoundItem, event.x_root, event.y_root )
    FoundTuple=mycanvas.find_overlapping(x, y, x+1, y+1)
    print( "Found Tuple: ", FoundTuple )
    # use coordinates relative to the canvas
#    ItemNdx=items.index(FoundItem)
#    print( "ItemNdx: ", ItemNdx )
    menu.tk_popup(event.x_root, event.y_root)

在 Python 的 Tkinter 中,找出用户点击了哪个图像(项目/标签 ID)的最简单方法是什么?


用 Window 图像监控图像

想知道 canvas 是什么样子的:

这是三台显示器 eDP-1-1 之一的部分。给出最坏的情况,有四个 windows 打开:

Window 堆叠顺序还不完美,因为 wmctrl 用于在桌面上全部打开 windows,但尚未按堆叠顺序进行任何排序。

所以用户会点击离他们想要的图像左上角最近的地方 select。用户还可以单击未被 window 覆盖的空白监视器区域以 select 监视器图像。 - 本网站的 Firefox 浏览器

标签电流也是一折

我输入了这段代码:

tag_current=event.widget.find_withtag("current")
print ("tag_current: ", tag_current)

结果是这样的:

('Item: ', 1, [985.0, 565.0])
('Item: ', 8, [25.0, 25.0])
('Item: ', 15, [505.0, 25.0])
('Item: ', 28, [1362.0, 31.0])
('Item: ', 35, [949.0, 167.0])
('Item: ', 42, [1050.0, 583.0])
('Item: ', 49, [83.0, 52.0])
('Item: ', 56, [26.0, 188.0])
('Item: ', 63, [998.0, 594.0])
('Item: ', 70, [25.0, 25.0])
('Item: ', 77, [1091.0, 644.0])
('Item at 26.0, 188.0 ', (70,))
('Item at 998.0, 594.0 ', (64,))
('tag_current: ', (41,))

tag_current 应该是 42 但被报告为 41.

63 报告为 6456 报告为 70 的问题大致相同(之前报告为 57 上次作业是 运行).


12 小时更新

12 小时后,我越来越近了。需要将 Window 坐标(三台显示器的整个桌面)转换为 canvas 坐标(其中一台显示器上的一个 Python 程序):

def popup(event):
    global FoundItem, MouseXY
    x = mycanvas.canvasx(event.x)
    y = mycanvas.canvasy(event.y)
    MouseXY=(x, y)
    print( "Adjusted x, y: ", x, y )
    FoundItem=mycanvas.find_closest(x, y)

希望今晚问题能得到解决...

找出"which image (tag/ tag ID) a user has clicked on"的方法是使用标签current。规范的 tcl/tk 文档对 current 标签进行了如下说明:

The tag current is managed automatically by Tk; it applies to the current item, which is the topmost item whose drawn area covers the position of the mouse cursor (different item types interpret this in varying ways; see the individual item type documentation for details). If the mouse is not in the canvas widget or is not over an item, then no item has the current tag.

这是一个人为设计的示例,它将打印出与您单击的任何项目相关联的标签。请注意,即使您滚动 canvas.

它也能正常工作
import tkinter as tk

def callback(event):
    tags = canvas.itemcget("current", "tags")
    label.configure(text=f"you clicked on {tags}")

root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=300)
label = tk.Label(root)
ysb = tk.Scrollbar(root, orient="vertical", command=canvas.yview)
xsb = tk.Scrollbar(root, orient="horizontal", command=canvas.xview)
canvas.configure(yscrollcommand=ysb.set, xscrollcommand=xsb.set)

root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)

canvas.grid(row=0, column=0, sticky="ew")
xsb.grid(row=1, column=0, sticky="ew")
ysb.grid(row=0, column=1, sticky="ns")
label.grid(row=2, columnspan=2, sticky="ew")

x = 10
y = 10
for color in ("red", "orange", "yellow", "green", "blue", "black", "bisque"):
    canvas.create_rectangle(x, y, x+100, y+100,
                            outline=color, fill=color,
                            tags=(color,)
    )
    x += 50
    y += 50
canvas.configure(scrollregion=canvas.bbox("all"))
canvas.bind("<Button-1>", callback)

root.mainloop()

这里是让它工作的最终解决方案:

def popup(event):
    global FoundItem
#    print( "Root x, y: ", event.x_root, event.y_root )
#    print( "event x, y: ", event.x, event.y )
    FoundItem=mycanvas.find_closest(event.x, event.y)
    menu.tk_popup(event.x_root, event.y_root)

您可以删除注释(# 字符)以在您的终端中查看 x,y 坐标。

  • .tk_popup.post 命令需要屏幕桌面坐标:(event.x_root, event.y_root)
  • .find_closest 命令需要 Canvas 坐标:(event.x, event.y)