我正在尝试为自己编写一个有趣的项目,这是一个用Python编写的截图工具。我遇到了一个问题,就是我要在屏幕上绘制一个矩形,获取坐标,然后截取这个区域的截图。我大部分时间都在工作,但是当选择项下方的窗口更新时,它会破坏矩形的绘制。
以下是显示问题的视频:https://gfycat.com/EmotionalThankfulFlycatcher
我已经尝试阅读Xlib文档,看看是否有一种方法可以轻松处理这个问题,但是找不到任何东西。我可以尝试的另一个选择是截取整个屏幕的截图,然后选择一个而不是占用现场桌面的区域。
无论如何我可以处理这个问题,而不是采用整个桌面的截图并裁剪它的路线?
import sys
from Xlib import X, display, Xutil, xobject, Xcursorfont
class xselect:
def __init__(self):
# X display
self.d = display.Display()
# Screen
self.screen = self.d.screen()
# Draw on the root window (desktop surface)
self.window = self.screen.root
def select_region(self):
# Set cursor to crosshair
font = self.d.open_font('cursor')
cursor = font.create_glyph_cursor(font, Xcursorfont.crosshair,
Xcursorfont.crosshair+1,
(65535, 65535, 65535), (0, 0, 0))
self.window.grab_pointer(1, X.PointerMotionMask|X.ButtonReleaseMask|X.ButtonPressMask,
X.GrabModeAsync, X.GrabModeAsync, X.NONE, cursor, X.CurrentTime)
colormap = self.screen.default_colormap
color = colormap.alloc_color(0, 0, 0)
# Xor it because we'll draw with X.GXxor function
xor_color = color.pixel ^ 0xffffff
self.gc = self.window.create_gc(
line_width = 1,
line_style = X.LineSolid,
fill_style = X.FillOpaqueStippled,
fill_rule = X.WindingRule,
cap_style = X.CapButt,
join_style = X.JoinMiter,
foreground = xor_color,
background = self.screen.black_pixel,
function = X.GXxor,
graphics_exposures = False,
subwindow_mode = X.IncludeInferiors,
)
done = False
started = False
start = dict(x=0, y=0)
end = dict(x=0, y=0)
last = None
while not done:
e = self.d.next_event()
# Window has been destroyed, quit
if e.type == X.DestroyNotify:
sys.exit(0)
# Mouse button press
elif e.type == X.ButtonPress:
# Left mouse button?
if e.detail == 1:
start = dict(x=e.root_x, y=e.root_y)
started = True
# Right mouse button?
elif e.detail == 3:
sys.exit(0)
# Mouse button release
elif e.type == X.ButtonRelease:
end = dict(x=e.root_x, y=e.root_y)
if last:
self.draw_rectangle(start, last)
done = True
pass
# Mouse movement
elif e.type == X.MotionNotify and started:
if last:
self.draw_rectangle(start, last)
last = None
last = dict(x=e.root_x, y=e.root_y)
self.draw_rectangle(start, last)
pass
# Keyboard key
elif e.type == X.KeyPress:
sys.exit(0)
elif e.type == X.EnterNotify:
print(' EnterNotify')
self.d.ungrab_pointer(0)
self.d.flush()
coords = self.get_coords(start, end)
if coords['width'] <= 1 or coords['height'] <= 1:
sys.exit(0)
else:
return coords
def get_coords(self, start, end):
safe_start = dict(x=0, y=0)
safe_end = dict(x=0, y=0)
if start['x'] > end['x']:
safe_start['x'] = end['x']
safe_end['x'] = start['x']
else:
safe_start['x'] = start['x']
safe_end['x'] = end['x']
if start['y'] > end['y']:
safe_start['y'] = end['y']
safe_end['y'] = start['y']
else:
safe_start['y'] = start['y']
safe_end['y'] = end['y']
return {
'start': {
'x': safe_start['x'],
'y': safe_start['y'],
},
'end': {
'x': safe_end['x'],
'y': safe_end['y'],
},
'width' : safe_end['x'] - safe_start['x'],
'height': safe_end['y'] - safe_start['y'],
}
def draw_rectangle(self, start, end):
coords = self.get_coords(start, end)
self.window.rectangle(
self.gc,
coords['start']['x'],
coords['start']['y'],
coords['end']['x'] - coords['start']['x'],
coords['end']['y'] - coords['start']['y']
)
答案 0 :(得分:0)
我自己还是X11的新手,但是stackoverflow上的X11标签已经死了,所以无论如何我都会尝试回答。
要获取屏幕截图,请查看this。您想使用XGetImage,它允许您指定所需的矩形。
现在绘制矩形,据我所知,在根窗口上绘图可能非常不合适。您可以改为创建一个透明背景的全屏窗口。例如,这也允许您为矩形周围的区域提供更暗的色调。