2

I'm writing a Python program that is basically the Snipping Tool. I'd like to be able to run my program, select the area for my screenshot using my mouse to click and drag, and then have the program save this image.

I was trying it out with 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 doesnt let the user click and drag. Does anyone know how I could do this? I found some examples online but they're all hundreds of lines long and I don't think this simple program should be that long (but I could be wrong).

Thanks!

Brett Holmes
  • 397
  • 5
  • 20
Julian
  • 503
  • 1
  • 6
  • 14
  • Hi, welcome to SO, don't use a link alone in your post, include the code you want to show us. The link could go dead in a few months or years, which will make the question useless. Copy and paste the code, and include the link as a source ! :) – Alexandre Beaudet Apr 18 '18 at 14:13
  • Rather than trying to create a snipping tool from scratch, why not simply use a [sub-process](https://stackoverflow.com/questions/204017/how-do-i-execute-a-program-from-python-os-system-fails-due-to-spaces-in-path) to run the Windows Snipping Tool? – Christian Dean Apr 18 '18 at 14:14
  • 1
    Thank you both! If I run Snipping Tool using Python, will I be able to automatically save the picture? I want to avoid having to click on "Save", choosing the folder, and then saving it manually. – Julian Apr 18 '18 at 14:32

1 Answers1

2

Here is the code I have for a project I'm working on (hope this helps). I figured out how to draw on the actual screen NOT just a static image!

from tkinter import *
import pyautogui

import datetime

class Application():
    def __init__(self, master):
        self.master = master
        self.rect = None
        self.x = self.y = 0
        self.start_x = None
        self.start_y = None
        self.curX = None
        self.curY = None

        # root.configure(background = 'red')
        # root.attributes("-transparentcolor","red")

        root.attributes("-transparent", "blue")
        root.geometry('400x50+200+200')  # set new geometry
        root.title('Lil Snippy')
        self.menu_frame = Frame(master, bg="blue")
        self.menu_frame.pack(fill=BOTH, expand=YES)

        self.buttonBar = Frame(self.menu_frame,bg="")
        self.buttonBar.pack(fill=BOTH,expand=YES)

        self.snipButton = Button(self.buttonBar, width=3, command=self.createScreenCanvas, background="green")
        self.snipButton.pack(expand=YES)

        self.master_screen = Toplevel(root)
        self.master_screen.withdraw()
        self.master_screen.attributes("-transparent", "blue")
        self.picture_frame = Frame(self.master_screen, background = "blue")
        self.picture_frame.pack(fill=BOTH, expand=YES)

    def takeBoundedScreenShot(self, x1, y1, x2, y2):
        im = pyautogui.screenshot(region=(x1, y1, x2, y2))
        x = datetime.datetime.now()
        fileName = x.strftime("%f")
        im.save("snips/" + fileName + ".png")

    def createScreenCanvas(self):
        self.master_screen.deiconify()
        root.withdraw()

        self.screenCanvas = Canvas(self.picture_frame, cursor="cross", bg="grey11")
        self.screenCanvas.pack(fill=BOTH, expand=YES)

        self.screenCanvas.bind("<ButtonPress-1>", self.on_button_press)
        self.screenCanvas.bind("<B1-Motion>", self.on_move_press)
        self.screenCanvas.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.recPosition()

        if self.start_x <= self.curX and self.start_y <= self.curY:
            print("right down")
            self.takeBoundedScreenShot(self.start_x, self.start_y, self.curX - self.start_x, self.curY - self.start_y)

        elif self.start_x >= self.curX and self.start_y <= self.curY:
            print("left down")
            self.takeBoundedScreenShot(self.curX, self.start_y, self.start_x - self.curX, self.curY - self.start_y)

        elif self.start_x <= self.curX and self.start_y >= self.curY:
            print("right up")
            self.takeBoundedScreenShot(self.start_x, self.curY, self.curX - self.start_x, self.start_y - self.curY)

        elif self.start_x >= self.curX and self.start_y >= self.curY:
            print("left up")
            self.takeBoundedScreenShot(self.curX, self.curY, self.start_x - self.curX, self.start_y - self.curY)

        self.exitScreenshotMode()
        return event

    def exitScreenshotMode(self):
        print("Screenshot mode exited")
        self.screenCanvas.destroy()
        self.master_screen.withdraw()
        root.deiconify()

    def exit_application(self):
        print("Application exit")
        root.quit()

    def on_button_press(self, event):
        # save mouse drag start position
        self.start_x = self.screenCanvas.canvasx(event.x)
        self.start_y = self.screenCanvas.canvasy(event.y)

        self.rect = self.screenCanvas.create_rectangle(self.x, self.y, 1, 1, outline='red', width=3, fill="blue")

    def on_move_press(self, event):
        self.curX, self.curY = (event.x, event.y)
        # expand rectangle as you drag the mouse
        self.screenCanvas.coords(self.rect, self.start_x, self.start_y, self.curX, self.curY)

    def recPosition(self):
        print(self.start_x)
        print(self.start_y)
        print(self.curX)
        print(self.curY)

if __name__ == '__main__':
    root = Tk()
    app = Application(root)
    root.mainloop()
Brett La Pierre
  • 463
  • 5
  • 15
  • 1
    I tried this but it apparently only works on one monitor: `pyautogui` doesn't support multiple monitors yet. Any other methods out there?? – RufusVS Apr 11 '21 at 21:03