python tkinter画布“透明”

2024-05-16 09:21:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我想透明是我要找的词。希望我的描述能解释清楚。

我有一张几十年前基于时间的数据图表。很简单地设置为每x像素显示一天,除非放大。我想有一个框,可能沿着5x100的线,出现在图形的顶部,所以当我移动鼠标在图形上时,框将移动并与鼠标保持同步。另一个词显示了在5个最远的日子里发生的事情“x前几天”。另外,当计算平均值时,随着新数据的到来,下一个值会下降多少。当然,我希望底层的图形化数据显示在透明框的上方,勾勒出所讨论的日期。这可能会变得疯狂到一个更宽的盒子,有两个区域是浅灰色或类似的颜色,以显示有问题的区域,但彩色区域被许多天隔开(可能是多个透明窗口,也可以一起跟踪)。这对tkinter可行吗?从我所做的研究来看,如果使用

root.attributes('alpha', .30)

会不会有用。这听起来不像我能做的那样,因为它最终会使图形对它下面的任何东西都透明。

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

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

attributes

就在根级别与单独的“窗口”级别,所以上面的代码(被严重切碎)不起作用……或者它会起作用。我还没有机会尝试任何事情来看看会发生什么…那将在今晚晚些时候。有点希望现在问问能省点时间,你永远不知道还有谁需要帮助。


Tags: 数据selfalpha图形区域图表时间像素
3条回答

如果我明白你想做什么,那就太难了。

设置窗口属性可以很好地使窗口透明。代码属性中有一个小问题,以连字符开头,但如果不是这样,您就解决了:

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

不过,听起来你希望Box成为图形窗口的嵌入部分,而不是它自己的顶层窗口,用户可以拖动它,等等。不幸的是,Tkinter没有任何子窗口的概念,它没有暴露足够的本地内容,你需要通过创建一个不可移动的窗口和手动移动它以跟踪另一个窗口的移动。所以,你没有窗口,这意味着你没有窗口透明度。

显然,Box是某种小部件,比如FrameCanvas。但是小部件没有透明度。

Box可以只是绘制到与Graph相同的Canvas上的元素的集合。这看起来很有希望……但是没有一种方法处理α透明度。(其中一些确实处理了全部或全部透明,但这没有帮助。)

处理透明度的一件事是PhotoImage。所以,如果你把Box从屏幕上画出来,得到结果内容作为PhotoImage,添加alpha(例如,通过PIL),然后create_image结果…关闭,但不抽雪茄。根据底层Tk库的设置,Tkinter可能只绘制具有1位透明度的像素映射,或者完全忽略透明度。(尝试在PIL中加载alpha透明的PNG文件并在画布上绘制它们。)因此,除非您希望某个应用程序在某些系统上看起来正确,在其他系统上根本不绘制长方体,在其他系统上绘制不透明,否则这是一个死胡同。

那么,还剩下什么?仅手动合成:在单独的屏幕外窗口上绘制GraphBox,获取像素,使用PIL合成它们,然后create_image得到结果。

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

使用PIL库中的模块,可以创建具有所需透明度的图像。(RGBA)把它放到画布上。图像的透明度应该可以工作,至少从我测试过的情况来看是这样。您应该只需要Image和ImageTk模块。

也许这能给你一些想法:

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()

相关问题 更多 >