前回 GtkWindow の枠を消した、これで Google Chrome みたいなウインドウ…
とか書いたけどウインドウ自体を透過させなきゃ四角いウインドウしか作れない。
透明にできれば角を丸くなんかは DrawingArea でなんとかなるはず。
python – Making Gtk.Window Transparent? – Ask Ubuntu
アッサリ見つかった。
ついでに自分のストックから PyGtk 版も出てきた。
せっかくなので PyGtk との違いを見るため両方で書いてみる。
透明なだけでは面白くないので透過付き画像を表示させる処理も。
私は絵心が壊滅的なので Text という文字を Gimp で書いただけですが…
アーカイブも置いておきますので自作して試してくださると嬉しい。
visual.tar.gz
PyGtk
#!/usr/bin/env python #-*- coding:utf-8 -*- import gtk, cairo class ColormapWin(gtk.Window): """ PyGtk(GTK2) Version """ def __init__(self): """ gtk.main_quit is Double Click """ gtk.Window.__init__(self) self.connect("delete-event", gtk.main_quit) self.connect("expose-event", self.on_expose) # GdkColormap screen = self.get_screen() colormap = screen.get_rgba_colormap() if colormap != None and screen.is_composited(): self.set_colormap(colormap) else: print "no Composited..." self.set_app_paintable(True) # Transparent background image self.pixbuf = gtk.gdk.pixbuf_new_from_file("test.xpm") # Mouse Click self.set_events(gtk.gdk.BUTTON_PRESS_MASK) self.connect("button-press-event", self.on_button_press_event) # self.set_decorated(False) self.resize(320, 240) self.show_all() def on_expose(self, widget, event=None): """ cr is gtk.gdk.CairoContext """ cr = widget.window.cairo_create() cr.set_source_rgba(1.0, 1.0, 1.0, 0.0) cr.set_operator(cairo.OPERATOR_SOURCE) cr.set_source_pixbuf(self.pixbuf, 0, 0) cr.paint() def on_button_press_event(self, widget, event=None): """ Mouse Drag and Quit """ if event.type == gtk.gdk.BUTTON_PRESS: self.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time) elif event.type == gtk.gdk._2BUTTON_PRESS: gtk.main_quit() ColormapWin() gtk.main()
pygi
#!/usr/bin/env python #-*- coding:utf-8 -*- from gi.repository import Gtk, Gdk, GdkPixbuf import cairo class VisualWin(Gtk.Window): """ PyGI(GTK3) Version """ def __init__(self): """ Gtk.main_quit is Double Click """ Gtk.Window.__init__(self) self.connect("delete-event", Gtk.main_quit) # 'expose-event' to 'draw' self.connect("draw", self.on_draw) # GdkColormap to GdkVisual screen = self.get_screen() visual = screen.get_rgba_visual() if visual != None and screen.is_composited(): self.set_visual(visual) else: print "no Composited..." self.set_app_paintable(True) # Transparent background image self.pixbuf = GdkPixbuf.Pixbuf.new_from_file("test.xpm") # Mouse Click self.set_events(Gdk.EventMask.BUTTON_PRESS_MASK) self.connect("button-press-event", self.on_button_press_event) # self.set_decorated(False) self.resize(320, 240) self.show_all() def on_draw(self, widget, cr): """ cr is cairo.Context """ cr.set_source_rgba(1.0, 1.0, 1.0, 0.0) cr.set_operator(cairo.OPERATOR_SOURCE) Gdk.cairo_set_source_pixbuf(cr, self.pixbuf, 0, 0) cr.paint() def on_button_press_event(self, widget, event, data=None): """ Mouse Drag and Quit """ if event.type == Gdk.EventType.BUTTON_PRESS: self.begin_move_drag(event.button, event.x_root, event.y_root, event.time) elif event.type == Gdk.EventType.DOUBLE_BUTTON_PRESS: Gtk.main_quit() VisualWin() Gtk.main()
Fedora でも Ubuntu でも問題ない。
枠も無くウインドウは透過しているけど画像は綺麗に表示できている。
PyGtk と PyGI もあまり違いは無いようだ。
GdkColormap が GdkVisual に変わったくらいで後はもうお馴染みの違いだけ。
デスクトップアクセサリを作る程度ならこれで簡単に作れるかな。
と思ったけど。
GNOME 3 を強制フォールバックにしたら真っ黒に、2D では合成できないようだ。
Lubuntu でもダメだった。
これじゃ「透過するアプリですヨン」って配れないじゃん。
デスクトップ Linux は仮想マシンな人がほとんどという現実だもの。
つまり Google Chrome みたいなウインドウはこの方法では作れないよ。
うーん、まだまだ勉強しなければ。