How to take screenshots using Python using a click-and-drag method like Snipping Tool?
I’m writing a Python program that is basically a screenshot tool. I want to be able to run my program, click and drag with the mouse to select my screenshot area, and then let the program save this image.
I’m trying to use the code found here: http://pyscreenshot.readthedocs.io/en/latest/
#-- include('examples/showgrabfullscreen.py') --#
import pyscreenshot as ImageGrab
if __name__ == '__main__':
# grab fullscreen
im = ImageGrab.grab()
# save image file
im.save('screenshot.png')
# show image in a window
im.show()
#-#
(under Grab and show part of the screen), but this doesn’t let the user click and drag. Does anyone know what I should do? I found some examples online, but they all have hundreds of lines long, and I don’t think this simple program should be that long (but I could be wrong).
Thanks!
Solution
I solved this problem by drawing on a transparent layer. This will allow the user to see through invisible drawing layers and provide a surface for drawing the cut box. When the user releases the screenshot frame feature, it breaks the invisible layer and captures the box coordinates. It will then take a screenshot within the captured coordinates and create + save this time-stamped image to a directory called “snips” (adjust it at will).
from tkinter import *
import pyautogui
import datetime
def take_bounded_screenshot(x1, y1, x2, y2):
image = pyautogui.screenshot(region=(x1, y1, x2, y2))
file_name = datetime.datetime.now().strftime("%f")
image.save("snips/" + file_name + ".png")
class Application():
def __init__(self, master):
self.snip_surface = None
self.master = master
self.start_x = None
self.start_y = None
self.current_x = None
self.current_y = None
root.geometry('400x50+200+200') # set new geometry
root.title('Lil Snippy')
self.menu_frame = Frame(master)
self.menu_frame.pack(fill=BOTH, expand=YES, padx=1, pady=1)
self.buttonBar = Frame(self.menu_frame, bg="")
self.buttonBar.pack()
self.snipButton = Button(self.buttonBar, width=5, height=5, command=self.create_screen_canvas, background="green")
self.snipButton.pack()
self.master_screen = Toplevel(root)
self.master_screen.withdraw()
self.master_screen.attributes("-transparent", "maroon3")
self.picture_frame = Frame(self.master_screen, background="maroon3")
self.picture_frame.pack(fill=BOTH, expand=YES)
def create_screen_canvas(self):
self.master_screen.deiconify()
root.withdraw()
self.snip_surface = Canvas(self.picture_frame, cursor="cross", bg="grey11")
self.snip_surface.pack(fill=BOTH, expand=YES)
self.snip_surface.bind("<ButtonPress-1>", self.on_button_press)
self.snip_surface.bind("<B1-Motion>", self.on_snip_drag)
self.snip_surface.bind("<ButtonRelease-1>", self.on_button_release)
self.master_screen.attributes('-fullscreen', True)
self.master_screen.attributes('-alpha', .3)
self.master_screen.lift()
self.master_screen.attributes("-topmost", True)
def on_button_release(self, event):
self.display_rectangle_position()
if self.start_x <= self.current_x and self.start_y <= self.current_y:
print("right down")
take_bounded_screenshot(self.start_x, self.start_y, self.current_x - self.start_x, self.current_y - self.start_y)
elif self.start_x >= self.current_x and self.start_y <= self.current_y:
print("left down")
take_bounded_screenshot(self.current_x, self.start_y, self.start_x - self.current_x, self.current_y - self.start_y)
elif self.start_x <= self.current_x and self.start_y >= self.current_y:
print("right up")
take_bounded_screenshot(self.start_x, self.current_y, self.current_x - self.start_x, self.start_y - self.current_y)
elif self.start_x >= self.current_x and self.start_y >= self.current_y:
print("left up")
take_bounded_screenshot(self.current_x, self.current_y, self.start_x - self.current_x, self.start_y - self.current_y)
self.exit_screenshot_mode()
return event
def exit_screenshot_mode(self):
self.snip_surface.destroy()
self.master_screen.withdraw()
root.deiconify()
def on_button_press(self, event):
# save mouse drag start position
self.start_x = self.snip_surface.canvasx(event.x)
self.start_y = self.snip_surface.canvasy(event.y)
self.snip_surface.create_rectangle(0, 0, 1, 1, outline='red', width=3, fill="maroon3")
def on_snip_drag(self, event):
self.current_x, self.current_y = (event.x, event.y)
# expand rectangle as you drag the mouse
self.snip_surface.coords(1, self.start_x, self.start_y, self.current_x, self.current_y)
def display_rectangle_position(self):
print(self.start_x)
print(self.start_y)
print(self.current_x)
print(self.current_y)
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()