Saving screen-shot of tkinter window as image

In summary: The flags “include_layered_windows” and “all_screens” can be used to capture the current window or all the screens.
  • #1
Eclair_de_XII
1,083
91
TL;DR Summary
Using PIL and win32gui in order to capture tkinter window as image, then save to file. It's always off-center, and I haven't a clue why.
Python:
from PIL import ImageGrab
from win32gui import GetWindowRect

def find_img_loc():
    k=1
    folder=sep.join((getcwd(),'screenshots'))
    initial_file='screenshot'+str(k)
    filename=lambda x: sep.join((folder,x+'.png'))
    while exists(filename(initial_file)):
        k+=1
        n=len(str(k-1))
        initial_file=initial_file[:-n]+str(k)
    kw={
        'initialfile':initial_file,\
        'defaultextension':'png',\
        'initialdir':folder,\
        'filetypes':[('.png files only','*.png')]
        }
    filename=filedialog.asksaveasfilename(**kw)
    return filename

def save_image(root):
    if not exists('screenshots'):
        mkdir('screenshots')
    root.update()
    HWND = root.winfo_id()  # get the handle of the canvas
    rect = GetWindowRect(HWND)  # get the coordinate of the canvas
    I am = ImageGrab.grab(rect)  # get image of the current location
    filename=find_img_loc()
    if not filename:
        return
    else:
        im.save(filename,format='png')
  
if __name__ == '__main__':
    root=Tk()
    lines='Sample text here','More sample text...','One more for the road.'
    for n, text in enumerate(lines):
        Label(root,text=text).grid(row=n)
    save_image(root)
    root.destroy()

This code was actually from:

https://stackoverflow.com/questions/9886274/how-can-i-convert-canvas-content-to-an-image
 
Last edited:
Technology news on Phys.org
  • #3
It was both.

The actual window looks like this:

actual.png
but the saved image looks like this:
screenshot4.png
In any case, I resolved the issue (partially) by using pyscreenshot.grab and manually tinkering with the capture dimensions. It was not efficient, I confess, but it did the trick alright

Python:
from os import mkdir, getcwd
from os.path import exists, sep

from pyscreenshot import grab

def find_img_loc():
    k=1
    folder=sep.join((getcwd(),'screenshots'))
    initial_file='screenshot'+str(k)
    filename=lambda x: sep.join((folder,x+'.png'))
    while exists(filename(initial_file)):
        k+=1
        n=len(str(k-1))
        initial_file=initial_file[:-n]+str(k)
    kw={
        'initialfile':initial_file,\
        'defaultextension':'png',\
        'initialdir':folder,\
        'filetypes':[('.png files only','*.png')]
        }
    filename=filedialog.asksaveasfilename(**kw)
    return filename

def save_image(im):
    if not exists('screenshots'):
        mkdir('screenshots')
    filename=find_img_loc()
    if not filename:
        return
    else:
        im.save(filename,format='png')

def save_image2(root):
    root.update()
    geometry=root.winfo_geometry()
    position=geometry.split('+')
    dimension=position[0].split('x')
    xlen=dimension[0]
    ylen=dimension[1]
    xpos=position[1]
    ypos=position[2]
    geo_list=(xpos,ypos,xlen,ylen)
    geometry=()
    k=1.25
    for n,g in enumerate(geo_list):
        g=int(g)
        g=k*g
        if n == 0:
            g+=10
        g=int(g)
        if n>1:
            h=geo_list[n-2]
            h=int(h)
            h=k*h
            k*=1.075
            h=int(h)
            geometry+=(g+h,)
        else:
            geometry+=(g,)
    im=grab(bbox=geometry)
    save_image(im)

if __name__ == '__main__':
    root=Tk()
    root.geometry('400x400+400+100')
    Label(root,text='Yabba dabba doo').grid()
    save_image1(root)
 
  • #4
Could it be that the screenshot you captured included more than just that one text window? If you manually capture a screenshot of that window, and then paste it into, say, Paint or other graphics app, do you get just that single window or do you get more?

Some documentation I found here says this. Note the last sentence.
PIL.ImageGrab.grab(bbox=None, include_layered_windows=False, all_screens=False, xdisplay=None)
Take a snapshot of the screen. The pixels inside the bounding box are returned as an “RGBA” on macOS, or an “RGB” image otherwise. If the bounding box is omitted, the entire screen is copied.
 

FAQ: Saving screen-shot of tkinter window as image

What is a screen-shot in tkinter?

A screen-shot in tkinter is a capture of the current state of a tkinter window or frame. It is essentially an image that represents what is currently being displayed on the screen.

How do I save a screen-shot of a tkinter window as an image?

To save a screen-shot of a tkinter window as an image, you can use the built-in function grab() from the tkinter library. This function takes a snapshot of the current state of the window and returns an Image object which can then be saved as an image file.

What format can I save the screen-shot in?

The grab() function in tkinter allows you to save the screen-shot in various image formats, such as .png, .jpg, or .gif. You can specify the desired format when saving the image.

Can I save a screen-shot of a specific part of the tkinter window?

Yes, you can specify the region of the window you want to capture by passing in the coordinates of the desired area to the grab() function. This way, you can save a screen-shot of a specific part of the window instead of the entire window.

Is there a way to automate the process of saving screen-shots of tkinter windows?

Yes, you can use the after() method in tkinter to create a loop that continuously captures and saves screen-shots at a set interval. This can be useful for creating a time-lapse of a tkinter application or for capturing and analyzing changes in the window over time.

Back
Top