python - python tkinter canvas将背景图像放在中心
问题描述
全部
这是我第一次使用 Tkinter。
我的工作是加载图像,在对象上绘制边界框并给它们正确的标签,如下所示:
这是我的代码
class ExampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.x = 0
self.y = 0
self.img = ImageTk.PhotoImage(file = "0.png")
self.canvas = tk.Canvas(self, width=1080, height=720)
self.canvas.create_image(20, 20, anchor=NW, image=self.img)
self.canvas.pack()
self.canvas.bind("<ButtonPress-1>", self.on_button_press)
self.canvas.bind("<B1-Motion>", self.on_move_press)
self.canvas.bind("<Motion>", self.moving)
self.start_x = None
self.start_y = None
self.rect = None
def right_click(self, event):
self.canvas.delete(self.canvas.find_closest(event.x, event.y))
def moving(self, event):
all_item = self.canvas.find_all()
for i in all_item[1:]:
for i in all_item:
self.canvas.itemconfig(i, width=2.0, outline='red')
target = self.canvas.find_closest(event.x, event.y)[0]
self.canvas.itemconfig(target, width=4.0, outline='yellow')
def on_button_press(self, event):
self.start_x = event.x
self.start_y = event.y
self.rect = self.canvas.create_rectangle(self.x, self.y, 1, 1, width=2.0, outline='red')
def on_move_press(self, event):
curX, curY = (event.x, event.y)
self.canvas.coords(self.rect, self.start_x, self.start_y, curX, curY)
def on_button_release(self, event):
pass
if __name__ == "__main__":
app = ExampleApp()
app.mainloop()
我想要的是当我在矩形内移动鼠标时,它会变成黄色。
问题是只有当鼠标正好在矩形的边缘时矩形才会变成黄色。
因为背景图片也是画布项目之一,所以 find_closest 函数将始终
当鼠标不在矩形边缘时返回图片。
有人有更好的主意吗??
解决方案
对于填充的矩形,您只需要
create_rectangle(..., activeoutline="yellow")
没有使用功能moving()
。
对于空矩形,您必须获取所有矩形并使用矩形使用canvas.bbox(id)
的获取区域(x1,y1,x2,y2)
并与event.x, event.y
要仅检查矩形,我将标签添加到矩形
self.canvas.create_rectangle(..., tag='rect')
后来我只能得到矩形
all_rect = self.canvas.find_withtag('rect')
def moving(self, event):
all_rect = self.canvas.find_withtag('rect')
x = event.x
y = event.y
for i in all_rect:
x1, y1, x2, y2 = self.canvas.bbox(i)
if x1 <= x <= x2 and y1 <= y <= y2:
self.canvas.itemconfig(i, width=4.0, outline='yellow')
else:
self.canvas.itemconfig(i, width=2.0, outline='red')
最终而不是使用find_withtag()
,bbox()
你可以使用 list 来保持
(rect_id, (x1,y1,x2,y3), text_id)
并使用它moving()
来查找矩形,然后您也可以更改矩形中的文本。
完整的示例代码。
我添加了重叠的矩形来测试它是否会改变两个矩形的颜色。
import tkinter as tk
from PIL import ImageTk
class ExampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.x = 0
self.y = 0
self.img = ImageTk.PhotoImage(file="image.jpg")
self.canvas = tk.Canvas(self, width=1080, height=720)
self.canvas.pack()
self.canvas.bind("<ButtonPress-1>", self.on_button_press)
self.canvas.bind("<B1-Motion>", self.on_move_press)
self.canvas.bind("<Motion>", self.moving)
self.canvas.create_image(20, 20, anchor='nw', image=self.img)
self.canvas.create_rectangle(50, 50, 100, 100, width=2.0, outline='red', tag='rect')
self.canvas.create_rectangle(200, 200, 250, 250, width=2.0, outline='red', tag='rect')
self.canvas.create_rectangle(75, 75, 225, 225, width=2.0, outline='red', tag='rect')
self.start_x = None
self.start_y = None
self.rect = None
def right_click(self, event):
self.canvas.delete(self.canvas.find_closest(event.x, event.y))
def moving(self, event):
all_rect = self.canvas.find_withtag('rect')
x = event.x
y = event.y
for i in all_rect:
x1, y1, x2, y2 = self.canvas.bbox(i)
if x1 <= x <= x2 and y1 <= y <= y2:
self.canvas.itemconfig(i, width=4.0, outline='yellow')
else:
self.canvas.itemconfig(i, width=2.0, outline='red')
def on_button_press(self, event):
self.start_x = event.x
self.start_y = event.y
self.rect = self.canvas.create_rectangle(self.x, self.y, 1, 1, width=2.0, outline='red', tag='rect')
def on_move_press(self, event):
curX, curY = (event.x, event.y)
self.canvas.coords(self.rect, self.start_x, self.start_y, curX, curY)
def on_button_release(self, event):
pass
if __name__ == "__main__":
app = ExampleApp()
app.mainloop()
编辑:使用列表(rect_id, (x1,y1,x2,y3), text_id)
更改矩形和文本颜色的代码。我on_button_release()
用来将新矩形添加到此列表中。
import tkinter as tk
from PIL import ImageTk
class ExampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.x = 0
self.y = 0
self.img = ImageTk.PhotoImage(file="image.jpg")
self.canvas = tk.Canvas(self, width=1080, height=720)
self.canvas.pack()
self.canvas.bind("<ButtonPress-1>", self.on_button_press)
self.canvas.bind("<ButtonRelease-1>", self.on_button_release)
self.canvas.bind("<B1-Motion>", self.on_move_press)
self.canvas.bind("<Motion>", self.moving)
self.canvas.create_image(20, 20, anchor='nw', image=self.img)
self.all_rect = []
rect_id = self.canvas.create_rectangle(50, 50, 100, 100, width=2.0, outline='red')
text_id = self.canvas.create_text(55, 57, text='A', fill="red")
self.all_rect.append((rect_id, (50, 50, 100, 100), text_id))
rect_id = self.canvas.create_rectangle(200, 200, 250, 250, width=2.0, outline='red')
text_id = self.canvas.create_text(205, 207, text='B', fill="red")
self.all_rect.append((rect_id, (200, 200, 250, 250), text_id))
rect_id = self.canvas.create_rectangle(75, 75, 225, 225, width=2.0, outline='red')
text_id = self.canvas.create_text(80, 82, text='C', fill="red")
self.all_rect.append((rect_id, (75, 75, 225, 225), text_id))
self.start_x = None
self.start_y = None
self.rect = None
def right_click(self, event):
self.canvas.delete(self.canvas.find_closest(event.x, event.y))
def moving(self, event):
x = event.x
y = event.y
for rect_id, bbox, text_id in self.all_rect:
x1, y1, x2, y2 = bbox
if x1 <= x <= x2 and y1 <= y <= y2:
self.canvas.itemconfig(rect_id, width=4.0, outline='yellow')
if text_id:
self.canvas.itemconfig(text_id, fill='yellow')
else:
self.canvas.itemconfig(rect_id, width=2.0, outline='red')
if text_id:
self.canvas.itemconfig(text_id, fill='red')
def on_button_press(self, event):
self.start_x = event.x
self.start_y = event.y
self.rect = self.canvas.create_rectangle(self.x, self.y, 1, 1, width=2.0, outline='red')
def on_move_press(self, event):
curX, curY = (event.x, event.y)
self.canvas.coords(self.rect, self.start_x, self.start_y, curX, curY)
def on_button_release(self, event):
curX, curY = (event.x, event.y)
x1, x2 = sorted((curX, self.start_x)) # I need `x1 <= x2` in `moving()`
y1, y2 = sorted((curY, self.start_y)) # I need `y1 <= y2` in `moving()`
self.all_rect.append((self.rect, (x1, y1, x2, y2), None) )
if __name__ == "__main__":
app = ExampleApp()
app.mainloop()
推荐阅读
- java - System.load('native library') 无法从浏览器处理小程序
- security - Profile参数login/password_downwards_compatibility是什么意思?
- c# - 将对象转换为类型而不进行装箱
- python - es demux 错误:尝试让我的计算机与 Python 对话时无法查看
- tomcat - 为什么 nginx 不做简单的负载均衡。Tomcat 实例。错误请求 400
- html - 动画效果从顶部获取文本并使用 css 在 div 中显示
- ios - 如何使用 EventKit 删除某些/特定事件
- angular - 如何在 Visual Studio 2017 中使用 ASP.NET Core 调试 Angular 5
- asp.net-core-mvc - NET Core Web 应用程序中是否可以引用另一个 NET Core Web 应用程序项目并重用类型和视图?
- dependency-injection - 将 Play 依赖注入模块配置为 trait