你如何截取 Tkinter 中特定小部件的屏幕截图?
How do you take a screenshot of a particular widget in Tkinter?
如何截取特定小部件的屏幕截图?搜索时,我不断收到“如何截取整个屏幕的屏幕截图”或“如何截取 window 的屏幕截图”,但我想知道如何准确截取一个小部件(一个框架)的屏幕截图。恐怕这个论坛会要求我给他们一个代码片段,而实际上我不知道该怎么做。所以我只是问这是否可能,以及如何去做。
PS:如果可以只给一个函数 widget 变量,然后它会去搜索那个 widget 然后截取它的精确屏幕截图,我将非常感激。我知道有 pyautogui 可以搜索图像,我只是不知道我到底需要做什么,因为这个框架不是图像,它总是不时地变化,所以自动化可能会混淆。
也许你可以获取该帧的坐标,然后根据该坐标截屏。这应该有效
PS: I would really appreciate if it is possible to just give a function the widget variable, and then it would go searching for that widget and then take a precise screenshot of it.
不,没有可以截取小部件屏幕截图的功能。你可以做的是使用 PIL
来截取图像。为此,您需要框架的坐标,您可以使用小部件的方法动态获取它。
首先你需要安装PIL
,所以:
pip install Pillow
如果在 Linux 上,则 PIL.ImageGrab
将不起作用,因此请安装另一个用于截屏的库,而不是 PIL
:
pip install pyscreenshot
这是一个模块化代码,您可以通过将小部件作为参数传递给函数来与任何小部件一起使用:
from PIL import ImageGrab # If on Linux, use `import pyscreenshot as ImageGrab` after installing it
def capture(wid,file_name='img',file_format='png'):
"""Take screenshot of the passed widget"""
x0 = wid.winfo_rootx()
y0 = wid.winfo_rooty()
x1 = x0 + wid.winfo_width()
y1 = y0 + wid.winfo_height()
im = ImageGrab.grab(bbox=(x0, y0, x1, y1)) # bbox means boundingbox, which is shown in the image below
im.save(f'{file_name}.{file_format}') # Can also say im.show() to display it
现在您只需将此功能实现到您的代码中,这是一个示例:
from tkinter import *
from PIL import ImageGrab # If on Linux, use `import pyscreenshot as ImageGrab` after installing it
root = Tk()
def capture(wid,file_name='img',file_format='png'):
"""Take screenshot of the passed widget"""
x0 = wid.winfo_rootx()
y0 = wid.winfo_rooty()
x1 = x0 + wid.winfo_width()
y1 = y0 + wid.winfo_height()
im = ImageGrab.grab((x0, y0, x1, y1))
im.save(f'{file_name}.{file_format}') # Can also say im.show() to display it
frame = Frame(root,bg='red',width=100,height=185)
frame.pack()
frame.pack_propagate(0) # Make it not auto-resize according to widgets
for i in range(5):
Button(frame,text=f'Button {i}').pack()
Button(root,text='Take screenshot',command=lambda: capture(frame,img_name='frame',img_format='png')).pack()
root.mainloop()
如果您想知道传入 bbox
的坐标指的是什么,那么:
如何截取特定小部件的屏幕截图?搜索时,我不断收到“如何截取整个屏幕的屏幕截图”或“如何截取 window 的屏幕截图”,但我想知道如何准确截取一个小部件(一个框架)的屏幕截图。恐怕这个论坛会要求我给他们一个代码片段,而实际上我不知道该怎么做。所以我只是问这是否可能,以及如何去做。
PS:如果可以只给一个函数 widget 变量,然后它会去搜索那个 widget 然后截取它的精确屏幕截图,我将非常感激。我知道有 pyautogui 可以搜索图像,我只是不知道我到底需要做什么,因为这个框架不是图像,它总是不时地变化,所以自动化可能会混淆。
也许你可以获取该帧的坐标,然后根据该坐标截屏。这应该有效
PS: I would really appreciate if it is possible to just give a function the widget variable, and then it would go searching for that widget and then take a precise screenshot of it.
不,没有可以截取小部件屏幕截图的功能。你可以做的是使用 PIL
来截取图像。为此,您需要框架的坐标,您可以使用小部件的方法动态获取它。
首先你需要安装PIL
,所以:
pip install Pillow
如果在 Linux 上,则 PIL.ImageGrab
将不起作用,因此请安装另一个用于截屏的库,而不是 PIL
:
pip install pyscreenshot
这是一个模块化代码,您可以通过将小部件作为参数传递给函数来与任何小部件一起使用:
from PIL import ImageGrab # If on Linux, use `import pyscreenshot as ImageGrab` after installing it
def capture(wid,file_name='img',file_format='png'):
"""Take screenshot of the passed widget"""
x0 = wid.winfo_rootx()
y0 = wid.winfo_rooty()
x1 = x0 + wid.winfo_width()
y1 = y0 + wid.winfo_height()
im = ImageGrab.grab(bbox=(x0, y0, x1, y1)) # bbox means boundingbox, which is shown in the image below
im.save(f'{file_name}.{file_format}') # Can also say im.show() to display it
现在您只需将此功能实现到您的代码中,这是一个示例:
from tkinter import *
from PIL import ImageGrab # If on Linux, use `import pyscreenshot as ImageGrab` after installing it
root = Tk()
def capture(wid,file_name='img',file_format='png'):
"""Take screenshot of the passed widget"""
x0 = wid.winfo_rootx()
y0 = wid.winfo_rooty()
x1 = x0 + wid.winfo_width()
y1 = y0 + wid.winfo_height()
im = ImageGrab.grab((x0, y0, x1, y1))
im.save(f'{file_name}.{file_format}') # Can also say im.show() to display it
frame = Frame(root,bg='red',width=100,height=185)
frame.pack()
frame.pack_propagate(0) # Make it not auto-resize according to widgets
for i in range(5):
Button(frame,text=f'Button {i}').pack()
Button(root,text='Take screenshot',command=lambda: capture(frame,img_name='frame',img_format='png')).pack()
root.mainloop()
如果您想知道传入 bbox
的坐标指的是什么,那么: