注册 | 登录

python tkinter canvas 'transparent'

itPublisher 分享于




'''Tkinter教程之Canvas篇(1)''' # 提供可以用来进行绘图的Container,支持基本的几何元素,使用Canvas进行绘图时,所有的操作都是通过Canvas,不是通过它的元素

I think transparent is the right word I'm looking for. Hopefully my description will explain it properly no matter what.

I have a graph of time based data going back decades. Pretty much simply setup to show one day per x-pixel, unless zoomed in closer. I would like to have a box, maybe along the lines of 5x100, appear on top of the graph so when I move the mouse over the graph the box will move and keep pace with the mouse. Anotherwords showing what was happening in the 5 furthest days 'x number of days prior'. Anotherwords when computing an average going forward what are the next values to be falling off as new data arrives. Naturally I want the underlying graphed data to be displayed with the transparent box on top of it outlining the days in question. This may get crazy enough to be a much wider box with two areas that are colored light grey or something like that to show the areas in question but the colored areas are separated by numerous days(could be multiple transparent windows that are tracked together as well. Is this feasible with tkinter? From the research I've been doing it's questionable if using

root.attributes('alpha', .30)

would work or not. It doesn't sound like I could do something like as it would end up making the graph transparent to whatever is underneath it.

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

If I understand correctly I have to use


right at the root level versus the individual 'window' level so the above (severely chopped down) code wouldn't work...or would it. I haven't had a chance to try anything out yet to see what happens...that will be later on this evening. Kinda hoping to save myself a little time by asking now and you never know who else may need the help sometime.

python tkinter
  this question
edited Jan 6 '14 at 23:22 Bryan Oakley 147k 11 154 271 asked Jan 6 '14 at 21:50 confused 335 1 5 11      Does this have to be with Tkinter? Because if I understand what you're asking for, it's going to be very hard to do, and it would be a lot easier with, e.g., PySide or wx or almost anything else. –  abarnert Jan 6 '14 at 23:01


2 Answers

If I understand what you're trying to do, it's going to be pretty hard.

Setting window attributes works just fine to make a window transparent. You've got a minor problem in the code—attributes start with a hyphen—but otherwise you've got it right:

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

However, it sounds like you want that Box to be an embedded part of the graph window, not its own top-level window that can be dragged around by the user, etc. Unfortunately, Tkinter does not have any notion of child windows, and it doesn't expose nearly enough of the native stuff you'd need to fake them by creating an immobile window and manually moving it to track the movements of another window. So, you don't have a window, which means you don't have window transparency.

The obvious thing for Box to be is some kind of widget, like a Frame or Canvas. But widgets don't have transparency.


'''Tkinter教程之Canvas篇(3)''' '''16.移动item''' # -*- coding: cp936 -*- # move指定x,y在偏移量 from Tkinter import *root = Tk()# 创建一个Canvas,设

Box could instead be just a collection of elements drawn onto the same Canvas as the Graph. That seems promising… but none of the Canvas methods handle alpha transparency. (Some of them do handle all-or-nothing transparency, but that doesn't help.)

One thing that does handle transparency is PhotoImage. So, if you draw Box off-screen, get the resulting contents as a PhotoImage, add the alpha (e.g., via PIL), then create_image the result… close, but no cigar. Depending on the settings of the underlying Tk library, Tkinter may just draw the pixmap with 1-bit transparency or ignore transparency completely. (Experiment with loading alpha-transparent PNG files in PIL and drawing them on a Canvas.) So, unless you want an app that looks right on some systems, doesn't draw the Box at all on others, and draws it opaque on others, this is a dead end.

So, what's left? Only manual compositing: Draw the Graph and the Box on separate off-screen windows, get the pixmaps, use PIL to compose them, and create_image the result.

At which point you're probably better off just using something like PIL's ImageDraw or a more powerful library to construct the pixmap in the first place. Or, of course, using a more powerful GUI library than Tk, like Qt or wx.

  this answer
answered Jan 6 '14 at 23:02 abarnert 174k 11 223 304      I knew from what I had read thus far that it sounded really questionable. It's something I'm going to have to play with and maybe try a few other ideas as well. I wouldn't mind staying with Tk since I've only used it thus far for anything graphing related so I'll probably have to try to come with some other way of doing what I'm trying to accomplish in terms of showing what former data is about to be taken out of the average equation. –  confused Jan 6 '14 at 23:35      @confused: After writing this, I discovered it's even more fun than I thought. I can't find anything that lets you get the pixmap of an off-screen window on Windows that works on Mac, or any way to convert an EPSF (which you can get directly from the Canvas) to a pixmap with a default Windows PIL/Pillow install, which means I can't even find a way to manually composite things… So I think you may have to draw the graph and box outside of Tk (with PIL, GraphicsMagick, etc., whatever) so you can composite them. –  abarnert Jan 6 '14 at 23:54


Maybe this can give you some ideas to play with:

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

#pil image with transparency
    from PIL import Image, ImageTk
except ImportError:
    pim ='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)

  this answer
answered Jan 8 '14 at 9:00 Oblivion 721 4 6



'''Tkinter教程之Canvas篇(2)''' '''9.创建item的tags''' # -*- coding: cp936 -*- # 使用属性tags设置item的tag # 使用Canvas的方法gettags获取指定item的tags








您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱