python - 如何单击并拖动已插入 tkinter 画布上另一个图像顶部的图像
问题描述
我在 tkinter 画布上有一张厨房桌子的图像。前景对象图像(例如,杯子)被插入到桌子图像的顶部。杯子图像具有 alpha 通道以删除其局部背景,因此杯子似乎坐在桌子上。背景图像和前景图像都以标准方式添加到画布中,使用:
canvas.create_image()
上面描述的一切都有效。
目标是:当鼠标悬停在杯子上时,在杯子图像周围放置一个圆圈(这样用户就知道可以拾取物品),然后允许用户单击杯子图像并将其拖动到桌子上的新位置(即画布)。
我尝试将鼠标按下事件绑定到圆圈(参见下面的代码)。为此,我遵循下面链接的一般示例;但是,在我的情况下它不起作用。
下面是重现问题的简化代码。代码将圆形放在画布上并定义了四个相关的回调。三是必绕;一个画布。期望是所有四个回调都应该工作。现实是通过 tags="click_zone" 绑定到圆圈的回调不起作用,而绑定到画布的回调起作用。
import cv2
from tkinter import Tk, Canvas
from PIL import ImageTk, Image
import time
class ClickZone:
def __init__(self, _canvas, _bbox):
self.click_zone = _canvas.create_oval(_bbox, tags=("click zone"))
_canvas.tag_bind("click zone", '<Enter>', self.on_enter)
_canvas.tag_bind("click zone", '<Leave>', self.on_leave)
_canvas.tag_bind("click zone", '<ButtonPress-1>', self.pick_up_object)
_canvas.bind("<ButtonRelease-1>", self.drop_object)
def drop_object(self, event):
print("Drop")
def pick_up_object(self, event):
print("Pick up")
def on_enter(self, event):
print("Enter")
def on_leave(self, event):
print("Leave")
root = Tk()
canvas = Canvas(root, width=800, height=600)
canvas.grid()
# Center of inserted object image
x_center_fg_object = 400
y_center_fg_object = 300
# Diameter of smallest circle fully enclosing inserted object image
fg_object_click_zone_radius = 250
# Bounding box around click zone circle
x0 = x_center_fg_object - fg_object_click_zone_radius
y0 = y_center_fg_object - fg_object_click_zone_radius
x1 = x_center_fg_object + fg_object_click_zone_radius
y1 = y_center_fg_object + fg_object_click_zone_radius
bbox = (x0, y0, x1, y1)
fg_object_click_zone = ClickZone(canvas, bbox)
root.mainloop()
最终,我想将拾取鼠标事件直接绑定到图像而不是圆圈;但是,我从未在网上找到有人成功将鼠标事件绑定到画布上的图像的示例。
解决方案
至少部分问题是因为你这样做了tags="click zone"
。标签应该是列表或元组,而不是字符串。由于 tcl 解释空格的方式,底层 tcl/tk 画布认为您正在应用两个标签:“click”和“zone”。因此,您对“点击区域”的绑定将不起作用。
另一个问题是画布对象绑定仅适用于对象本身。对于一个圆圈,这意味着<ButtonPress-1>
只有单击圆圈的轮廓而不是单击圆圈内部时才会起作用。如果您添加填充颜色,您将能够单击圆圈上的任意位置。
至于绑定到图像,其工作方式与绑定到任何其他画布对象完全相同。这个关于拖放的类似问题的答案有一个完整的工作解决方案:https ://stackoverflow.com/a/6789351/7432
推荐阅读
- kotlin - 密封类与现有类?
- javascript - Javascript:将 JQuery 等 CDN 从 HTML 文件中移出?
- prolog - Prolog 从集合中获得最大收益
- javascript - 如何在 Rails 中向全日历事件 url 添加 id?
- node.js - 在 Google Functions 中使用 child_process.exec 非常缓慢且随机
- node.js - 如何将对象从续集传递到车把部分?
- firebase - Firebase Firestore:如何按集合监控读取文档计数?
- gatsby - Gatsby/Reach 路由器 404,但页面呈现
- python - 多列分布拟合
- java - 如何通过 yarnClient 在代码中获取日志聚合