带有透明图像的可拖动 Tkinter 标签仍然覆盖来自父画布的图像 [英] Draggable Tkinter Label With Transparent Image Still Covers Image from Parent Canvas

查看:26
本文介绍了带有透明图像的可拖动 Tkinter 标签仍然覆盖来自父画布的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力在背景图像上添加可拖动标签,其中标签是具有透明背景的图像.用于标签的图像本身是透明的,但标签本身相对于其父画布并不透明.由于标签是可拖动的,我不能轻易地使用父图像作为标签,并将透明图像粘贴在顶部.

I am working on adding drag-able labels on top of a background image, where the labels are images with a transparent background. The images used for the label themselves are transparent, but the Label itself is not transparent in relation to its parent canvas. Since the labels are drag-able, I can't easily use the parent image for label, and paste the transparent image on top.

龙是一个可拖动的标签,背景是透明的,但是你看到标签本身并不透明,并且覆盖了画布图像.

The dragon is a drag-able label, with a transparent background, but you see that the label itself is not transparent, and covers the canvas image.

龙图像本身具有透明背景,因为正常背景是蓝色,所以我知道问题在于标签透明度.

The dragon image itself has a transparent background, as the normal background is blue, so I know the issue is with the label transparency.

期望的行为是允许标签透明,因此当标签上的图像是透明的时,标签应该显示到下面的图像.

The desired behavior would be to allow the label to be transparent, so when the image on the label is transparent, the label should show through to the image below.

这是一个最小的例子:

from PIL import Image, ImageTk
import numpy as np
import tkinter as tk

#Creates a blue square with a transparent border
blue_square_transparent_border = [[[0,0,0,0]]*100]*10 + [[[0,0,0,0]]*30 + [[0,0,255,255]]*40 + [[0,0,0,0]]*30]*40 + [[[0,0,0,0]]*100]*10
blue_square_transparent_border = np.array(blue_square_transparent_border, dtype='uint8')
#convert numpy array to PIL image
pil_image = Image.fromarray(blue_square_transparent_border)

root = tk.Tk()
root.configure(background='red')
#convert PIL image to tkinter image
tk_image = ImageTk.PhotoImage(pil_image)
#create label
image_label = tk.Label(root, image=tk_image)
image_label.pack()
root.mainloop()

我想看到的是一个蓝色方块,红色背景,没有边框.但是在上面的例子中,灰色的边框出现了,因为它是通过透明图像看到的标签;调整窗口大小时很容易看到这一点.我怀疑如果标签是透明的,这会解决我的问题.

What I would like to see is a blue square, on a red background, with no border. In the above example though, the border of grey appears, as it is the label being seen through the transparent image; it is easy to see this when you resize the window. I suspect if the label were transparent, this would solve my issues.

任何帮助都会很棒,谢谢!

Any help would be great, Thanks!

推荐答案

如果您想将部分透明的图像(如龙)拖到背景图像上,您可以使用 Canvas 来实现:

If you want to drag partially transparent images (like the dragon) over a background image, you can do it with a Canvas:

这个想法不是使用标签,而是使用 Canvascreate_image 方法.首先,使用 canvas.create_image(0, 0, image=background_image, anchor='nw') 显示您的背景图片,然后使用标签 'draggable' 显示所有可拖动的图片: canvas.create_image(x, y, image=draggable_image, anchor='nw', tag='draggable').最后,将标签draggable"绑定到鼠标事件.

The idea is not to use labels, but the create_image method of the Canvas. First, display your background image with canvas.create_image(0, 0, image=background_image, anchor='nw'), then display all the draggable images with the tag 'draggable': canvas.create_image(x, y, image=draggable_image, anchor='nw', tag='draggable'). Finally, bind the tag 'draggable' to mouse events.

这是一个例子:

import tkinter as tk
import numpy as np
from PIL import Image, ImageTk

# drag callbacks
dragged_item = None
current_coords = 0, 0

def start_drag(event):
    global current_coords
    global dragged_item
    result = canvas.find_withtag('current')
    if result:
        dragged_item = result[0]
        current_coords = canvas.canvasx(event.x), canvas.canvasy(event.y)
    else:
        dragged_item = None

def stop_drag(event):
    dragged_item = None

def drag(event):
    global current_coords
    xc, yc = canvas.canvasx(event.x), canvas.canvasy(event.y)
    dx, dy = xc - current_coords[0], yc - current_coords[1]
    current_coords = xc, yc
    canvas.move(dragged_item, dx, dy)


#Create pictures
blue_square_transparent_border = [[[0,0,0,0]]*100]*10 + [[[0,0,0,0]]*30 + [[0,0,255,255]]*40 + [[0,0,0,0]]*30]*40 + [[[0,0,0,0]]*100]*10
blue_square_transparent_border = np.array(blue_square_transparent_border, dtype='uint8')
pil_image = Image.fromarray(blue_square_transparent_border)

background_data = np.zeros((200, 400, 4))
background_data[:, :, 0] = 255 * np.ones((200, 400))
background_data[:, :, 3] = 255 * np.ones((200, 400))
background_data = np.array(background_data, dtype='uint8')
pil_image_bg = Image.fromarray(background_data)

# create GUI
root = tk.Tk()
background_image = ImageTk.PhotoImage(pil_image_bg)
tk_image = ImageTk.PhotoImage(pil_image)

canvas = tk.Canvas(root, width=400, height=200)
canvas.pack()
# bind 'draggable' tag to mouse events
canvas.tag_bind('draggable', '<ButtonPress-1>', start_drag)
canvas.tag_bind('draggable', '<ButtonRelease-1>', stop_drag)
canvas.tag_bind('draggable', '<B1-Motion>', drag)
# display pictures
canvas.create_image(0, 0, image=background_image, anchor='nw')
canvas.create_image(0, 0, image=tk_image, anchor='nw', tag='draggable')

root.mainloop()

这篇关于带有透明图像的可拖动 Tkinter 标签仍然覆盖来自父画布的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆