如何在MacOS上捕获tkinter窗口的图像(截图)

4
我已经使用Python Tkinter创建了一个GUI应用程序,用于分析实验室中的数据。其中有很多按钮、图形和画布小部件。希望能够通过单个按钮仅使用一次来截取整个窗口('root'),并将文件名适当地保存。下面是一个示例,演示如何使用Mac内置的“截图”应用程序 here
相关问题可以在这里这里这里找到,但都没有成功。最后一个链接这里几乎成功了,但保存的图像却是我的电脑桌面背景。我的电脑是Mac,运行的是MacOS Monterey 12.0.1。
'root'指的是Tkinter窗口。
root = tk.Tk()

在脚本开头出现,类似于示例中的'window'。下面的代码示例中,我正在使用PIL.ImageGrab

这是当前的代码,它可以获取我桌面背景不太有用的截图:

def screenshot():
    # retrieve the time string to use as a filename
    file_name = root.time_string[-6:]
    full_file_name = file_name + '_summary' + '.png'
    x = root.winfo_rootx() + root.winfo_x()
    y = root.winfo_rooty() + root.winfo_y()
    x1 = x + root.winfo_width()
    y1 = y + root.winfo_height()
    ImageGrab.grab().crop((x, y, x1, y1)).save(full_file_name)

我这样创建按钮:

我这样创建按钮:

screenshot_btn = tk.Button(root, text='Screenshot', command=lambda: screenshot(), font=('Verdana', 24), state=DISABLED)

我将按钮放在 'root' 中,代码如下:

screenshot_btn.grid(row=11, column=3)

[这是我在stackoverflow上的第一篇帖子。如果我首次尝试时没有完全遵循所有指南,请提前谅解。感谢您的耐心。]


1
你通过 ImageGrab.grab().save(full_file_name) 得到了什么?你有多个屏幕吗?你运行的是哪个Python版本?PIL的哪个版本? - Thingamabobs
1
请查看此链接:https://github.com/BoboTiG/python-mss/issues/134#issuecomment-567543451 - Delrius Euphoria
1
@CoolCloud 是的,这正是问题所在。我调整了安全设置,允许 PyCharm 访问屏幕录制功能,然后它就可以工作了!谢谢! - mathman
2个回答

1
首先,我没有关于抓取我的桌面的问题,但它显示了一个不正确裁剪的图像。
我找到了一个巧妙的解决方案。问题似乎出现在分辨率上。所以尺寸需要进行一些缩放。
我做的是获取 ImageGrab.grab().save(full_file_name) 的输出(没有裁剪),并测量所需图像区域的像素大小。这些维度将被称为 x_pixelsy_pixels
然后我在屏幕单位上测量了同一区域的实际窗口。我通过启动 mac 截图工具来完成这个操作,该工具显示了区域的尺寸。然后我将这些维度称为 x_screeny_screen。然后我按照以下方式修改了您的截图函数。
def screenshot():
    # retrieve the time string to use as a filename
    file_name = root.time_string[-6:]
    full_file_name = file_name + '_summary' + '.png'
    x = root.winfo_rootx()
    y = root.winfo_rooty()
    x1 = x + root.winfo_width()
    y1 = y + root.winfo_height()
    x_pixels = 337
    y_pixels = 79
    x_screen = 171
    y_screen = 41
    x = x*(x_pixels/x_screen)
    y = y*(y_pixels/y_screen)
    x1 = x1*(x_pixels/x_screen)
    y1 = y1*(y_pixels/y_screen)
    ImageGrab.grab().crop((x, y, x1, y1)).save(full_file_name)

请注意,我还删除了+root.winfo_x()+root.winfo_y()

结果如下所示。它并不完美,但我相信如果我更仔细地测量截图和窗口边界的像素,缩放会得到改进。

示例截图


谢谢@nikost。当我弄清楚主要问题——给PyCharm授予屏幕录制权限时,我遇到了你在这里描述的裁剪问题。你提供的解决方案起作用了。 - mathman

0

你是否有“Retina”显示器?ImageGrab无法考虑到从Mac的screencapture命令收集的144 DPI图像。您可以通过将所有x、y、x1、y1值乘以2来进行补偿(但如果需要考虑Mac窗口标题栏,则仍可能会错过一些内容)。

或者,使用pyscreenshot包(或窃取其代码...)。它使用screencapture的“-R”选项获取图像的正确边界。适用于像我这样的扩展监视器,其中x坐标小于0(因为它在主监视器的左侧)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接