1
votes

don be afraid of that big class - it was interesting for me to write so it could work in that universal way. it could be the parent-class for transparent elements, and not-parent. so, the trouble. it can make transparent the main gtk.Window, the gtk.EventBox as in example below, and other gtk.widgets, but it doesnot work with gtk.Layout, help me please. i think i wrote enough yet for send the question. sorry my English:)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import gtk
import cairo
class Transparent:
    def __init__(self,*rgba):
        Transparent.makeTransparent(self)
        if len(rgba)>0:
            self.rgba=rgba[0]
    @staticmethod
    def expose (widget, event):
        cr = widget.window.cairo_create()
        cr.set_operator(cairo.OPERATOR_CLEAR)
        cr.rectangle(event.area)
        cr.fill()
        cr.set_operator(cairo.OPERATOR_OVER)
        try:
            widget.rgba
        except AttributeError:
            widget.rgba=(0.0,0.0,0.0,0.0)
        cr.set_source_rgba(*widget.rgba)
        cr.rectangle(event.area)
        cr.fill()  
    @staticmethod
    def makeTransparent(thing,*rgba): 
        if len(rgba)>0:
            thing.rgba=rgba[0]   
        thing.expose=Transparent.expose
        thing.set_app_paintable(True)
        screen = thing.get_screen()
        rgba = screen.get_rgba_colormap()
        thing.set_colormap(rgba)
        thing.connect('expose-event', thing.expose)

win = gtk.Window()
Transparent.makeTransparent(win)

#works with EventBox:
eb=gtk.EventBox()
win.add(eb)
Transparent.makeTransparent(eb)

#but not with Layout:
#l=gtk.Layout(None,None)
#win.add(l)
#Transparent.makeTransparent(l)

win.show_all()
win.show()
gtk.main()
1
For one thing, you could make your code a little more readable. Use default arguments (rgba=(.0, .0, .0, .0)) instead of *rgba and checking its length. Some PEP8-like whitespaces would also be nice.liori
you are right, i wrote it at night, so forgot about default arguments, thanks:)scythargon

1 Answers

2
votes

Very nice... I've been learning this stuff and I like your code.

From the pygtk manual (emphasis added):

The gtk.Layout can also be drawn on similar to drawing on a gtk.DrawingArea. When handling expose events on a gtk.Layout, you must draw to the window specified by the bin_window attribute rather than the widget window attribute.

I think in your function you are getting the window attribute not the bin_window for cairo to draw on.

Modify the expose function to this:

@staticmethod
def expose (widget, event):
    if 'gtk.Layout' in str(type(widget)):
        cr=widget.bin_window.cairo_create()
    else:
        cr = widget.window.cairo_create()
    cr.set_operator(cairo.OPERATOR_CLEAR)
    cr.rectangle(event.area)
    cr.fill()
    cr.set_operator(cairo.OPERATOR_OVER)
    try:
        widget.rgba
    except AttributeError:
        widget.rgba=(0.0,0.0,0.0,0.0)
    cr.set_source_rgba(*widget.rgba)
    cr.rectangle(event.area)
    cr.fill()