目标是创建一个透明窗口,可以在其中标记任意屏幕上的内容(包括动态内容)。最终目的是将图形叠加在线上科学出版物中,单击并收集曲线上的点,并最终使用生成器函数对收集到的点进行曲线拟合。这包括画出线条、坐标轴、刻度线和其他内容。
2、解决方案
透明窗口
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):
self.point(cr, surface)
self.aperture(cr, surface)
self.positions(cr, surface)
self.crosshair(cr, surface)
self.index += 1
def point(self, cr, surface):
cr.set_operator(cairo.OPERATOR_OVER)
r, g, b, a = (0.0, 0.0, 0.0, 1.0)
cr.set_source_rgba(r, g, b, a)
cr.rectangle(self.x1, self.y1, 1, 1)
cr.fill()
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()
def positions(self, cr, surface):
cr.set_operator(cairo.OPERATOR_OVER)
for x, y in self.points:
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 <= x < self.xy[0] and 0 <= y < self.xy[1]:
cr.set_operator(cairo.OPERATOR_OVER)
cr.set_source_rgba(0.0, 0.0, 0.0, 1.0)
cr.rectangle(x, y, 1, 1)
cr.fill()
保存组合图像
def save_image(widget, event):
with Transparency(widget, self.index) as (cr, surface):
# Draw the overlay
self.point(cr, surface)
self.aperture(cr, surface)
self.positions(cr, surface)
self.crosshair(cr, surface)
# Get the underlying window contents
window_surface = widget.get_window().get_surface()
# Create a new surface with the combined contents
combined_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, *self.xy)
combined_cr = cairo.Context(combined_surface)
# Draw the underlying window contents onto the combined surface
combined_cr.set_source_surface(window_surface, 0, 0)
combined_cr.paint()
# Draw the overlay onto the combined surface
combined_cr.set_source_surface(surface, 0, 0)
combined_cr.paint()
# Save the combined image to a PNG file
filename = 'combined.png'
with open(filename, 'wb') as png:
combined_surface.write_to_png(png)
print(f'Saved combined image to {filename}')