Search code examples
python-3.xtkintertkinter-canvasimagegrab

Performing ImageGrab on tkinter Screen


I am trying to save a tkinter screen to a file (to later convert into a video).

I can't get the correct position of the canvas for using ImageGrab.

My relevant imports are:

import tkinter
import pyscreenshot as ImageGrab 

I am trying to save the screen using (after drawing the screen):

grab = ImageGrab.grab(bbox=canvas.bbox())
ImageGrab.grab_to_file(fileName,grab)

I don't know how to get the canvas position for using "ImageGrab.grab".

Is there any way to get the bounding box for the whole canvas, so as to later use ImageGrab to store a screenshot?

---Edit------------------------------------------------------------------

Solution:

box = (canvas.winfo_rootx(),canvas.winfo_rooty(),canvas.winfo_rootx()+canvas.winfo_width(),canvas.winfo_rooty() + canvas.winfo_height())
grab = ImageGrab.grab(bbox = box)
grab.save(file_path)

Solution

  • You have methods like winfo_x(), winfo_y() to get position inside parent widget (it doesn't have to be main window), and winfo_rootx(), winfo_rooty() to get position on screen.

    Effbot.org: Basic Widget Methods

    Code displays canvas' position on screen and inside parent Frame

    import tkinter as tk
    
    def callback():
        print('  root.geometry:', root.winfo_geometry())
        print('canvas.geometry:', canvas.winfo_geometry())
        print('canvas.width :', canvas.winfo_width())
        print('canvas.height:', canvas.winfo_height())
        print('canvas.x:', canvas.winfo_x())
        print('canvas.y:', canvas.winfo_y())
        print('canvas.rootx:', canvas.winfo_rootx())
        print('canvas.rooty:', canvas.winfo_rooty())
    
    root = tk.Tk()
    
    tk.Label(root, text='SOME WIDGETS IN ROOT').pack()
    
    frame = tk.Frame(root)
    frame.pack()
    
    tk.Label(frame, text='SOME WIDGETS IN FRAME').pack()
    
    canvas = tk.Canvas(frame, bg='green')
    canvas.pack()
    
    print('\n--- before mainloop start---\n')
    callback()
    
    print('\n--- after mainloop start ---\n')
    root.after(100, callback)
    
    root.mainloop()
    

    Example result

    --- before mainloop start ---
    
      root.geometry: 1x1+0+0
    canvas.geometry: 1x1+0+0
    canvas.width : 1
    canvas.height: 1
    canvas.x: 0
    canvas.y: 0
    canvas.rootx: 0
    canvas.rooty: 0
    
    --- after mainloop start ---
    
      root.geometry: 380x303+770+462
    canvas.geometry: 380x267+0+18
    canvas.width : 380
    canvas.height: 267
    canvas.x: 0
    canvas.y: 18
    canvas.rootx: 770
    canvas.rooty: 498