【kimol君的無聊小發明】—用python寫截圖小工具

2020-09-28 12:01:35

前言

今天我看了一下自己的資料夾,發現了自己寫了許多似乎很無聊的程式碼。於是乎,一個想法油然而生:「生活已經很無聊了,不如再無聊一點叭」。
說幹就幹,那就開一個專題,我們稱之為kimol君的無聊小發明
妙…啊~~~

今天要做的東西,就是用python寫一個截圖工具。想必大家平時截圖的時候很多都是用的微信的ALT+A或者是WINDOWS自帶的截圖軟體。作為技術宅的我,怎麼總是用別人的東西呢?
看我的,上圖:
在這裡插入圖片描述
效果還闊以,好歹這個小貓咪截出來也是有模有樣的~

一、技術實現

1. 相關庫

在python中可以實現截圖的庫有很多,這裡我用的是pyautogui,它可以對指定區域進行截圖:

import pyautogui

而介面部分(截圖的框選等)採用了tkinter庫:

import tkinter as tk

2. 定義視窗

定義一個透明的視窗,讓它的大小與螢幕一樣:

root = tk.Tk()
root.overrideredirect(True)         # 隱藏視窗的標題列
root.attributes("-alpha", 0.1)      # 視窗透明度10%
root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))
root.configure(bg="black")

注:alhpa引數用於設定透明度;geometry函數用於設定視窗大小;
建立一個子視窗,用於顯示框選區域:

# 再建立1個Canvas用於圈選
cv = tk.Canvas(root)
x, y = 0, 0
xstart,ystart = 0 ,0
xend,yend = 0, 0
rec = ''

3. 繪製工具條

繪製一個工具條,方便後續增加功能。講道理目前來說這個就是個雞肋(可以省去),但是如果後續還想晚上功能的話,會很有幫助。

canvas = tk.Canvas(root)
canvas.configure(width=300)
canvas.configure(height=100)
canvas.configure(bg="yellow")
canvas.configure(highlightthickness=0)  # 高亮厚度
canvas.place(x=(root.winfo_screenwidth()-500),y=(root.winfo_screenheight()-300))
canvas.create_text(150, 50,font='Arial -20 bold',text='ESC退出,假裝工具條')

4. 定義事件函數

監聽滑鼠和鍵盤事件,實時監控框選區域和截圖,具體的事件有:

# 繫結事件
canvas.bind("<B1-Motion>", move)   # 滑鼠左鍵移動->顯示當前遊標位置
root.bind('<Escape>',sys_out)      # 鍵盤Esc鍵->退出
root.bind("<Button-1>", button_1)  # 滑鼠左鍵點選->顯示子視窗 
root.bind("<B1-Motion>", b1_Motion)# 滑鼠左鍵移動->改變子視窗大小
root.bind("<ButtonRelease-1>", buttonRelease_1) # 滑鼠左鍵釋放->記錄最後遊標的位置
root.bind("<Button-3>",button_3)   #滑鼠右鍵點選->截圖並儲存圖片
root.mainloop()

監聽滑鼠遊標位置:

def move(event):
    global x, y ,xstart,ystart
    new_x = (event.x-x)+canvas.winfo_x()
    new_y = (event.y-y)+canvas.winfo_y()
    s = "300x200+" + str(new_x)+"+" + str(new_y)    
    canvas.place(x = new_x - xstart,y = new_y -ystart)   
    print("s = ", s)
    print(root.winfo_x(), root.winfo_y())
    print(event.x, event.y)

建立子視窗:

def button_1(event):
    global x, y ,xstart,ystart
    global rec
    x, y = event.x, event.y
    xstart,ystart = event.x, event.y
    print("event.x, event.y = ", event.x, event.y)
    xstart,ystart = event.x, event.y  
    cv.configure(height=1)
    cv.configure(width=1)
    cv.config(highlightthickness=0) # 無邊框
    cv.place(x=event.x, y=event.y)
    rec = cv.create_rectangle(0,0,0,0,outline='red',width=8,dash=(4, 4))

改變子視窗大小:

def b1_Motion(event):
    global x, y,xstart,ystart
    x, y = event.x, event.y
    print("event.x, event.y = ", event.x, event.y)
    cv.configure(height = event.y - ystart)
    cv.configure(width = event.x - xstart)
    cv.coords(rec,0,0,event.x-xstart,event.y-ystart)

鬆開滑鼠,記錄最後的遊標位置:

def buttonRelease_1(event):
    global xend,yend
    xend, yend = event.x, event.y

截圖並儲存圖片:

def button_3(event):
    global xstart,ystart,xend,yend
    cv.delete(rec)
    cv.place_forget()
    img = pyautogui.screenshot(region=[xstart,ystart,xend-xstart,yend-ystart]) # x,y,w,h
    img.save('screenshot.png')
    sys_out(None)

退出程式:

def sys_out(even):
    root.destroy()

二、後續改進

這個還有很多可以改進的地方。

  1. 截圖的時候會有dos視窗遮擋:這個解決辦法由很多,類似後臺啟動,或者將.py編譯為可執行檔案等等;
  2. 使用不方便,為了截圖還的執行程式碼:廢話!!!當然很不方便呀,不然怎麼說是個無聊的小發明呢。但是!!!它也不是一無事處,可以考慮把它放到後臺執行。同樣可以利用快捷鍵來喚醒它並完成截圖。
  3. 功能單一:這只是一個很簡單的demo,既然可以截圖了,那麼我們離錄屏還遠嗎?(正如本文開頭的動圖,右上角晃晃幾個大字「ApowerREC」,不給錢休想去掉,哼~)那麼,我們為何不自己寫一個呢?

寫在最後

最後,感謝各位大大的耐心閱讀~
慢著,大俠請留步… 動起可愛的雙手,來個贊再走唄 (๑◕ܫ←๑)