import os
import time
import json
import pynput
import ctypes
import threading
import tkinter as tk
from time import sleep
import tkinter.filedialog
from PIL import Image, ImageGrab,ImageTk
command_list = [] # 用来存储用户的操作
global isRunning
isRunning = True # 是否在运行,用于实现在按esc后退出的功能
startTime = 0 # 开始时间,会在之后进行初始化
def get_image(file_nam, width, height): # 读取背景图
im = Image.open(file_nam).resize((width, height))
return ImageTk.PhotoImage(im)
def on_key_press(key): # 当按键按下时记录
if key == pynput.keyboard.Key.esc: # 如果是esc
win.state('normal')
isRunning = False # 通知监听鼠标的线程
mouse = pynput.mouse.Controller() # 获取鼠标的控制器
mouse.click(pynput.mouse.Button.left) # 通过模拟点击鼠标以执行鼠标的线程,然后退出监听.
return False # 监听函数return False表示退出监听
command_list.append(("press", (str(key).strip("'")), time.time()-startTime))
def on_key_release(key): # 但按键松开时记录
command_list.append(("release", (str(key).strip("'")),time.time()-startTime))
def on_mouse_click(x, y, button, pressed):
if not isRunning: # 如果已经不在运行了
return False # 退出监听
if not pressed: # 如果是松开事件
return True # 不记录
command_list.append(("click", (x, y, str(button)), time.time() - startTime))
def start_key_listen(): # 用于开始按键的监听
with pynput.keyboard.Listener(on_press = on_key_press, on_release = on_key_release) as listener:
listener.join()
def start_mouse_listen(): # 用于开始鼠标的监听
with pynput.mouse.Listener(on_click = on_mouse_click) as listener:
listener.join()
def toFile(command_list, path): # 保存为文件,参数分别为操作记录和保存位置
with open(path, "w") as f:
f.write(json.dumps(command_list)) # 使用json格式写入
f.close()
class FreeCapture():
def __init__(self, win, img):
self.X = tkinter.IntVar(value = 0) # 变量X和Y用来记录鼠标左键按下的位置
self.Y = tkinter.IntVar(value = 0)
screenWidth = win.winfo_screenwidth() # 屏幕尺寸
screenHeight = win.winfo_screenheight()
self.top = tkinter.Toplevel(win, width = screenWidth, height = screenHeight)# 创建顶级组件容器
self.top.overrideredirect(True) # 不显示最大化、最小化按钮
self.canvas = tkinter.Canvas(self.top, bg = 'white', width = screenWidth, height = screenHeight)
self.image = tkinter.PhotoImage(file = img) # 显示全屏截图,在全屏截图上进行区域截图
self.canvas.create_image(screenWidth // 2, screenHeight // 2, image = self.image)
self.lastDraw = None
def onLeftButtonDown(event): # 鼠标左键按下的位置
self.X.set(event.x)
self.Y.set(event.y)
self.sel = True # 开始截图
self.canvas.bind('<Button-1>', onLeftButtonDown)
def onLeftButtonMove(event):
if not self.sel: # 鼠标左键移动,显示选取的区域
return
try: # 删除刚画完的图形,要不然鼠标移动的时候是黑乎乎的一片矩形
self.canvas.delete(self.lastDraw)
except Exception as e:
pass
self.lastDraw = self.canvas.create_rectangle(self.X.get(), self.Y.get(), event.x, event.y, outline = 'red')
def onLeftButtonUp(event): # 获取鼠标左键抬起的位置,保存区域截图
self.sel = False
try:
self.canvas.delete(self.lastDraw)
except Exception as e:
pass
time.sleep(0.5)
left, right = sorted([self.X.get(), event.x]) # 考虑鼠标左键从右下方按下而从左上方抬起的截图
top, bottom = sorted([self.Y.get(), event.y])
pic = ImageGrab.grab((left + 1, top + 1, right, bottom))
x = left+1, top+1, right, bottom
bbox = (x)
im = ImageGrab.grab(bbox)
im.save('../录制截图.png') # 参数 保存截图文件的路径
self.top.destroy() # 关闭当前窗口
with open('../坐标.txt', "w") as z:
z.write(str(x))
z.close()
self.canvas.bind('<B1-Motion>', onLeftButtonMove) # 按下左键
self.canvas.bind('<ButtonRelease-1>', onLeftButtonUp) # 抬起左键
self.canvas.pack(fill = tkinter.BOTH, expand = tkinter.YES) # 让canvas充满窗口,并随窗口自动适应大小
def screenShot():
win.state('icon') # 最小化主窗体
time.sleep(0.2)
im = ImageGrab.grab()
im.save('temp.png') # 暂存全屏截图
im.close()
w = FreeCapture(win, 'temp.png') # 进行自由截屏
threebutton.wait_window(w.top)
win.state('normal') # 截图结束,恢复主窗口,并删除temp.png文件
win.wm_attributes('-topmost',1) # 置顶页面
os.remove('temp.png')
def Start(): # 录制
win.state('icon') # 最小化主窗体
global startTime
startTime = time.time() # 初始化开始时间
key_listen_thread = threading.Thread(target = start_key_listen) # 创建用于监听按键的线程
mouse_listen_thread = threading.Thread(target = start_mouse_listen) # 创建用于监听鼠标的线程
key_listen_thread.start() # 运行线程
mouse_listen_thread.start()
key_listen_thread.join() # 等待线程结束,也就是等待用户按下esc
mouse_listen_thread.join()
toFile(command_list,'../录制记录.json') # 保存文件
def Finish(): # 终结程序
os._exit(0)
def thread_it(func, *args):
t = threading.Thread(target = func, args = args) # 创建
t.setDaemon(True) # 守护
t.start() # 启动
win = tk.Tk()
win.wm_attributes('-topmost', 1) # 置顶页面
win.title('应用执行框') # 设置窗口title和大小
win.geometry('200x200')
win.resizable(0, 0) # 防止用户调整尺寸
canvas = tk.Canvas(win, height = 500, width = 500) # 画布 设置背景图片
im_win = get_image('../录制背景图.png', width = 680, height = 650)
canvas.create_image(250, 250, image = im_win)
canvas.pack()
onebutton = tk.Button(win, bg = 'Light blue', text = "录制", width = 5, height = 2, command = lambda :thread_it(main))
twobutton = tk.Button(win, bg = 'Light blue', text = "关闭", width = 5, height =2 , command = lambda :thread_it(Finish))
threebutton = tk.Button(win, bg = 'Light blue', text = "截屏", width = 5, height = 2, command = lambda :thread_it(screenShot))
onebutton.place(x = 5, y = 150)
twobutton.place(x = 150, y = 150)
threebutton.place(x = 75, y =150)
win.mainloop()
自动化录制及手动截图
最新推荐文章于 2024-04-16 10:06:22 发布