我想開發一個透明的窗口,我可以在其上標記任何在我的屏幕上(包括動態)的窗口。 我的最終目標是覆蓋在線科學出版物中的圖表,點擊並累積沿曲線 的點,並最終使用生成器函數來曲線擬合所收集的點。 這將包括放置線和軸,刻度線和其他好東西。 但是,我試圖保持問題代碼非常簡單。如何標記透明pygtk pycairo窗口並保存組合圖像?
下面的代碼很好地完成了透明度部分(請批評和糾正)。 我已經做了大量的研究,以瞭解如何保存透明窗口的內容,並失敗。 我試圖弄清楚如何覆蓋任何東西(繪圖原語)並失敗。 我尋求任何和所有建議,推動這個項目,並打算使最終的代碼開源。
請幫忙。
#!/usr/bin/env python
"""
trans.py Transparent window with markup capability.
Goals:
1. make a transparent window that dynamically updates (working).
2. draw opaque points, lines, text, and more (unimplemented).
3. save window overlayed by opaque points to png (unimplemented).
4. toggle overlay on/off (unimplemented).
5. make cursor XOR of CROSSHAIR (unimplemented).
"""
import pygtk
pygtk.require('2.0')
import gtk, cairo
class Transparency(object):
def __init__(self, widget, index):
self.xy = widget.get_size()
self.cr = widget.window.cairo_create()
self.index = index
def __enter__(self):
self.cr.set_operator(cairo.OPERATOR_CLEAR)
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, *self.xy)
self.cr.rectangle(0.0, 0.0, *self.xy)
self.cr.fill()
return self.cr, self.surface
def __exit__(self, exc_type, exc_val, exc_tb):
filename = '%08d.png' % (self.index)
with open(filename, 'w+') as png:
self.surface.write_to_png(png)
print filename
self.cr.set_operator(cairo.OPERATOR_OVER)
class Expose(object):
def __init__(self):
self.index = 0
def __call__(self, widget, event):
with Transparency(widget, self.index) as (cr, surface):
# cr and surface are available for drawing.
pass
self.index += 1
def main():
x, y = 201, 201
win = gtk.Window(gtk.WINDOW_TOPLEVEL)
win.connect("destroy", lambda w: gtk.main_quit())
win.set_decorated(True)
win.set_app_paintable(True)
win.set_size_request(x, y)
win.set_colormap(win.get_screen().get_rgba_colormap())
win.connect('expose-event', Expose())
win.realize()
win.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.DIAMOND_CROSS))
win.show()
gtk.main()
if __name__ == "__main__":
main()
UPDATE!得到了大部分我需要的工作,除了BIG之外。 如何保存底層窗口和透明覆蓋圖組合形成的圖像? 積分可以放下,覆蓋可以使用vi風格的鍵盤控制來切換。 下面是最新的源:
#!/usr/bin/env python
"""
trans.py Transparent window with markup capability.
Goals:
1. make a transparent window that dynamically updates (working).
2. draw opaque points, lines, text, and more (working).
3. save window overlayed by opaque points to png (unimplemented).
4. toggle overlay on/off (working).
5. make cursor XOR of CROSSHAIR (using pixel-wise crosshair instead).
6. enable keyboard input in original emacs function table style (working).
"""
import pygtk
pygtk.require('2.0')
import gtk, cairo
from math import pi
class Transparency(object):
index = 0
def __init__(self, widget):
self.xy = widget.get_size()
self.cr = widget.window.cairo_create()
self.storing = False
def __enter__(self):
self.cr.set_operator(cairo.OPERATOR_CLEAR)
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, *self.xy)
self.cr.rectangle(0.0, 0.0, *self.xy)
self.cr.fill()
return self.cr, self.surface
def __exit__(self, exc_type, exc_val, exc_tb):
if self.storing:
filename = '%08d.png' % (Transparency.index)
with open(filename, 'w+') as png:
self.surface.write_to_png(png)
print filename
self.cr.set_operator(cairo.OPERATOR_OVER)
Transparency.index += 1
class Expose(object):
def __init__(self, window, xy):
self.keep, self.points, self.bare = False, set(), False
self.window = window
self.X, self.Y = self.xy = xy
self.x1, self.y1 = self.x0, self.y0 = self.xy[0]/2, self.xy[1]/2
self.window.connect("key_press_event", self.key_press_event)
self.window.set_events(gtk.gdk.KEY_PRESS_MASK)
self.window.set_flags(gtk.HAS_FOCUS | gtk.CAN_FOCUS)
self.window.grab_focus()
# function table for keyboard driving
self.function = [[self.noop for a in range(9)] for b in range(256)]
self.function[ord('q')][0] = self.quit # q for quit
self.function[ord('h')][0] = self.lf # h for left (vi-style)
self.function[ord('j')][0] = self.dn # j for down (vi-style)
self.function[ord('k')][0] = self.up # k for up (vi-style)
self.function[ord('l')][0] = self.rt # l for right (vi-style)
self.function[ord('h')][2] = self.lf # h for left (vi-style) with point
self.function[ord('j')][2] = self.dn # j for down (vi-style) with point
self.function[ord('k')][2] = self.up # k for up (vi-style) with point
self.function[ord('l')][2] = self.rt # l for right (vi-style) with point
self.function[ord('.')][0] = self.mark # . for point
self.function[ord(',')][0] = self.state # , to toggle overlay
def __call__(self, widget, event):
self.xy = widget.get_size()
self.x0, self.y0 = self.xy[0]/2, self.xy[1]/2
with Transparency(widget) as (cr, surface):
if not self.bare:
self.point( cr, surface)
self.aperture(cr, surface)
self.positions(cr, surface)
self.crosshair(cr, surface)
def aperture(self, cr, surface):
cr.set_operator(cairo.OPERATOR_OVER)
cr.set_source_rgba(0.5,0.0,0.0,0.5) # dim red transparent
cr.arc(self.x0, self.y0, self.x0, 0, pi*2)
cr.fill()
return self
def position(self, cr, surface, x, y, chosen):
cr.set_operator(cairo.OPERATOR_OVER)
#r, g, b, a = (0.0,0.0,0.0,1.0) if chosen else (0.0,0.0,1.0,0.5)
r, g, b, a = (0.0,0.0,0.0,1.0)
cr.set_source_rgba(r,g,b,a)
cr.rectangle(x, y, 1, 1)
cr.fill()
def crosshair(self, cr, surface):
for dx, dy in [(-2,-2),(-1,-1),(1,1),(2,2),(-2,2),(-1,1),(1,-1),(2,-2)]:
x, y = self.x1 + dx, self.y1 + dy
if 0 0))
def dn(self, c, n): self.newxy(0, +int(self.y1 0), 0)
def rt(self, c, n): self.newxy(+int(self.x1 127 else key
def key_press_event(self, widget, event):
keyname = gtk.gdk.keyval_name(event.keyval)
mask = (1*int(0 != (event.state>k.gdk. SHIFT_MASK))+
2*int(0 != (event.state>k.gdk.CONTROL_MASK))+
4*int(0 != (event.state>k.gdk. MOD1_MASK)))
self.keep = 0 != (mask & 2)
self.function[self.accept(event.keyval)][mask](keyname, event.keyval)
self(widget, event)
return True
def main():
x, y = xy = [201, 201]
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.connect("destroy", gtk.main_quit)
window.set_decorated(True)
window.set_app_paintable(True)
window.set_size_request(x, y)
window.set_colormap(window.get_screen().get_rgba_colormap())
window.connect('expose-event', Expose(window, xy))
window.realize()
window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.DIAMOND_CROSS))
window.show()
gtk.main()
if __name__ == "__main__":
main()
回答了很多我自己的問題。只有最大的一個仍然是: – jlettvin 2012-04-29 06:09:35
hi @jlettvin這是一個好主意,我想嘗試一下你的代碼。然而,你上面發佈的內容似乎被'十字線'和'dn'功能所破壞:例如'if 0 0))'。此外,'退出'等功能缺失......請你更新上面的代碼? – venzen 2013-12-16 04:34:59