python tkinter canvas'透明'

时间:2014-01-06 21:50:10

标签: python tkinter

我认为透明是我正在寻找的正确的词。希望无论如何,我的描述都会正确解释。

我有一张基于时间的数据图表可以追溯到几十年前。几乎只是设置为每x像素显示一天,除非放大更近。我希望有一个盒子,也许沿着5x100的线条出现在图表的顶部,所以当我将鼠标移动到图表上时,盒子将移动并跟上鼠标的步伐。另一个词显示在前5天的最前几天发生了什么'。计算平均值时的另一个词是随着新数据的到来,下一个值会下降的是什么。当然,我希望底层的图形数据显示在其顶部的透明框中,概述了相关的日期。这可能会变得更加疯狂,成为一个更宽的盒子,有两个浅灰色区域或类似的区域来显示有问题的区域,但彩色区域被分开了很多天(可能是多个透明的窗口,也被跟踪在一起这对tkinter来说是否可行?从研究开始,我一直在做这个问题,如果使用

root.attributes('alpha', .30)

会起作用吗?这听起来不像我可以做的事情,因为它最终会使图表对其下面的任何内容透明。

self.Graph.create_line()
self.Box.attributes('alpha', .30)

如果我理解正确,我必须使用

attributes

在根级别与单个“窗口”级别相关,因此上述(严重删除)代码将无法正常工作......或者是否可以。我还没有机会尝试任何事情,看看会发生什么......那将是今天晚上。有点希望通过现在询问节省一点时间,你永远不知道还有谁可能需要帮助。

3 个答案:

答案 0 :(得分:3)

如果我理解你要做的事情,那将会非常困难。

设置窗口属性可以很好地使窗口透明。你在代码属性中遇到了一个小问题,以连字符开头 - 否则你就做对了:

self.Box.attributes("-alpha", .30)

然而,听起来你希望Box成为图形窗口的嵌入部分,而不是它自己的顶级窗口,可以被用户拖动等等。不幸的是,Tkinter没有儿童窗户的任何概念,并没有通过创建一个不动的窗口并手动移动它来跟踪另一个窗口的移动,几乎没有暴露你需要伪造它们的本机东西。所以,你没有窗口,这意味着你没有窗口透明度。

Box显而易见的是某种小部件,例如FrameCanvas。但是小部件没有透明度。

Box可能只是与Canvas绘制在同一Graph上的元素集合。这似乎很有希望......但Canvas方法都没有处理alpha透明度。 (其中一些确实处理了全有或全无的透明度,但这没有帮助。)

处理透明度的一件事是PhotoImage。因此,如果您在屏幕外绘制Box,请将结果内容作为PhotoImage,添加alpha(例如,通过PIL),然后create_image结果...关闭,但不要雪茄。根据底层Tk库的设置,Tkinter可能只是绘制具有1位透明度的像素图或完全忽略透明度。 (尝试在PIL中加载alpha透明的PNG文件并在Canvas上绘制它们。)因此,除非你想要一个在某些系统上看起来正确的应用程序,否则不会在其他系统上绘制Box,并在其他系统上将其绘制为不透明,这是一个死胡同。

那么,还剩下什么?仅手动合成:在单独的离屏窗口上绘制GraphBox,获取像素图,使用PIL组合它们,以及create_image结果。

在这一点上,你可能最好只使用像PIL的ImageDraw或更强大的库来构建像素图。或者,当然,使用比Tk更强大的GUI库,如Qt或wx。

答案 1 :(得分:1)

也许这可以给你一些想法:

from tkinter import *

root = Tk()
c = Canvas(root, width=640, height=480, bd=0, highlightthickness=0)
c.create_line(0,240,640,240, fill='blue')
c.pack()

#pil image with transparency
try:
    from PIL import Image, ImageTk
except ImportError:
    pass
else:
    pim = Image.new('RGBA', (5,100), (0,255,0,64))
    photo = ImageTk.PhotoImage(pim)
    c.create_image(200,200, image=photo, anchor='nw')

#blank standard photoimage with red vertical borders
im = PhotoImage(width=7, height=480)
dat = ('red',)*480
im.put(dat, to=(0,0))
im.put(dat, to=(6,0))

box = c.create_image(0, 0, image=im, anchor='nw')

def on_motion(event):
    left,top = c.coords(box)
    dx = event.x - (left+7)
    c.move(box, dx, 0)

c.bind('<Motion>', on_motion)
root.mainloop()

答案 2 :(得分:0)

使用PIL库中的模块,您可以创建具有所需透明度的图像。 (RGBA)并将其放入画布。图像的透明度应该起作用,至少从我测试过的开始。您应该只需要Image和ImageTk模块。