该文章描述了一个使用Python实现的GUI录屏工具,主要利用Tkinter库构建界面,支持倒计时功能和帧率设置。用户可以通过菜单栏进行开始、暂停和结束录屏操作,录屏视频保存至桌面,倒计时默认为3秒,帧率默认为12fps,可自定义调整。
- import os
- from datetime import datetime
- import time
- from threading import Thread, Event
- from tkinter import Tk, Menu, Frame, Label, IntVar, Toplevel, Entry, Scale, HORIZONTAL, messagebox
- import numpy as np
- import cv2
- import pyautogui
-
-
- class Window(Tk):
- def __init__(self):
- super().__init__()
-
- # 倒计时标签对象
- self.lb = None
- # 倒计时标签数值
- self.lbNum = IntVar()
- self.lbNum.set(3)
- # 倒计时数值备份
- self.lbNumBack = 3
-
- # 帧率
- self.fps = 12
-
- # 录屏状态
- self.screencapState = False
- # 暂停状态
- self.screencapWaitState = Event()
- # 取消暂停
- self.screencapWaitState.set()
-
- # 倒计时状态
- self.countdownState = False
-
- self.gui()
- self.menu()
-
- def gui(self):
- """
- 主窗体
- :return:
- """
- # 设置窗体背景色
- self["background"] = "Crimson"
- # 设置Crimson色为透明
- self.attributes('-transparentcolor', 'Crimson')
- # 设置窗体透明度为80%
- self.attributes("-alpha", 0.8)
- # 获取主屏幕宽高
- mainWidth = self.winfo_screenwidth()
- mainHeight = self.winfo_screenheight()
- # 窗口宽高
- width = int(mainWidth * 0.4)
- height = int(mainHeight * 0.4)
- # 设置窗口大小与显示位置
- self.geometry(f'{width}x{height}+{int((mainWidth - width) / 2)}+{int((mainHeight - height) / 2)}')
- # 标题
- self.title("录屏工具")
- # 图标
- self.iconbitmap("logo.ico")
- # 倒计时标签
- f = Frame(self)
- self.lb = Label(
- f,
- textvariable=self.lbNum,
- fg='red',
- bg='Crimson',
- font=('微软雅黑', 66, 'bold')
- )
- self.lb.pack()
- # 水平垂直居中
- f.pack(expand=1)
-
- def menu(self):
- """
- 菜单栏
- :return:
- """
- menubar = Menu(self)
- # 操作
- operate = Menu(menubar, tearoff=0)
- menubar.add_cascade(label="操作", menu=operate)
- operate.add_command(label='开始', command=self.startScreencap)
- operate.add_command(label='暂停', command=self.waitScreencap)
- operate.add_separator()
- operate.add_command(label='结束', command=self.stopScreencap)
-
- # 操作
- setting = Menu(menubar, tearoff=0)
- menubar.add_cascade(label="设置", menu=setting)
- setting.add_command(label='倒计时', command=self.setCountdown)
- setting.add_separator()
- setting.add_command(label='帧率', command=self.setFps)
-
- # 关于
- about = Menu(menubar, tearoff=0)
- menubar.add_cascade(label='关于', menu=about)
- about.add_command(label='说明', command=self.instruction)
- about.add_separator()
- about.add_command(label='作者', command=self.author)
- self.config(menu=menubar)
-
- def setCountdown(self):
- """
- 设置倒计时弹窗
- :return:
- """
- # 设置主窗口不可操作
- self.attributes("-disabled", 1)
- # 弹窗
- t = Toplevel(self)
- # 弹窗宽高
- width = 250
- height = 120
- # 获取主屏幕宽高
- mainWidth = t.winfo_screenwidth()
- mainHeight = t.winfo_screenheight()
- # 设置窗口大小与显示位置
- t.geometry(f'{width}x{height}+{int((mainWidth - width) / 2)}+{int((mainHeight - height) / 2)}')
- # 禁止窗口缩放
- t.resizable(0, 0)
- # 标题
- t.title("倒计时设置")
- # 图标
- t.iconbitmap("logo.ico")
- # 输入框
- e = Entry(t,
- width=2,
- fg='red',
- font=('微软雅黑', 30, 'bold')
- )
- e.pack(pady=30)
- # 设置输入框焦点
- e.focus_set()
- # 设置输入框值
- e.insert(0, self.lbNumBack)
- # 绑定弹窗关闭事件
- t.protocol("WM_DELETE_WINDOW", lambda: self.setCountdownClose(e, t))
-
- def setCountdownClose(self, e, t):
- """
- 设置倒计时弹窗关闭事件
- :param e: 设置倒计时弹窗输入框对象
- :param t: 设置倒计时弹窗对象
- :return:
- """
- try:
- # 获取输入框数据
- num = int(e.get())
- # 更新倒计时标签数值
- self.lbNum.set(num)
- # 备份倒计时设置数值
- self.lbNumBack = num
- # 销毁设置倒计时数值弹窗
- t.destroy()
- # 设置主窗口可操作
- self.attributes("-disabled", 0)
- # 窗口保持在前面
- self.lift()
- except ValueError:
- pass
-
- def setFps(self):
- """
- 设置帧率弹窗
- :return:
- """
- # 设置主窗口不可操作
- self.attributes("-disabled", 1)
- # 弹窗
- t = Toplevel(self)
- # 弹窗宽高
- width = 250
- height = 120
- # 获取主屏幕宽高
- mainWidth = t.winfo_screenwidth()
- mainHeight = t.winfo_screenheight()
- # 设置窗口大小与显示位置
- t.geometry(f'{width}x{height}+{int((mainWidth - width) / 2)}+{int((mainHeight - height) / 2)}')
- # 禁止窗口缩放
- t.resizable(0, 0)
- # 标题
- t.title("帧率设置")
- # 图标
- t.iconbitmap("logo.ico")
- # 输入框
- e = Scale(t,
- width=60,
- from_=6,
- to=60,
- orient=HORIZONTAL)
- e.pack()
- e.set(self.fps)
- # 绑定弹窗关闭事件
- t.protocol("WM_DELETE_WINDOW", lambda: self.setFpsClose(e, t))
-
- def setFpsClose(self, e, t):
- """
- 设置倒计时弹窗关闭事件
- :param e: 设置滚动条对象
- :param t: 设置帧率弹窗对象
- :return:
- """
- try:
- # 获取滚动条数据
- num = int(e.get())
- self.fps = num
- # 销毁设置帧率弹窗
- t.destroy()
- # 设置主窗口可操作
- self.attributes("-disabled", 0)
- # 窗口保持在前面
- self.lift()
- except ValueError:
- pass
-
- @staticmethod
- def instruction():
- messagebox.showinfo('说明',
- '1、录屏区域为本软件窗口区域\n\n'
- '2、菜单栏进行录屏操作\n\n'
- '3、录屏视频位于桌面\n\n'
- '4、倒计时设置秒值-默认:3\n\n'
- '5、帧率常为12~24-默认:12')
-
- @staticmethod
- def author():
- messagebox.showinfo('作者', '小丫')
-
- def screencap(self):
- """
- 录屏
- :return:
- """
- # 倒计时
- self.countdown()
- # 编码格式
- fourcc = cv2.VideoWriter_fourcc(*'XVID')
- video = cv2.VideoWriter(os.path.join(os.path.join(os.path.expanduser("~"), 'Desktop'), datetime.now().strftime('%Y-%m-%d %H-%M-%S') + '.mp4'),
- fourcc,
- self.fps,
- pyautogui.screenshot(region=(
- self.winfo_x() + 4, self.winfo_y(), self.winfo_width(),
- self.winfo_height())).size
- )
- while self.screencapState:
- # 暂停
- self.screencapWaitState.wait()
- # 转为opencv的BGR格式
- imm = cv2.cvtColor(
- np.array(pyautogui.screenshot(
- region=(self.winfo_x() + 4, self.winfo_y(), self.winfo_width(), self.winfo_height()))),
- cv2.COLOR_RGB2BGR
- )
- # 写入视频
- video.write(imm)
- # 保存视频
- video.release()
-
- def startScreencap(self):
- """
- 开始录屏
- :return:
- """
- # 判断暂停状态
- if self.screencapWaitState.isSet():
- # 判断录屏状态
- if not self.screencapState:
- # 录制状态开启
- self.screencapState = True
- # 取消缩放
- self.resizable(0, 0)
- # 录屏
- ts = Thread(target=self.screencap)
- ts.daemon = True
- ts.start()
- else:
- # 判断倒计时状态
- if not self.countdownState:
- # 倒计时初始化
- self.lbNum.set(self.lbNumBack)
- # 显示标签
- self.lb.configure(fg="red")
- # 继续录屏
- tc = Thread(target=self.continueScreencap)
- tc.daemon = True
- tc.start()
-
- def continueScreencap(self):
- """
- 继续录屏
- :return:
- """
- # 倒计时
- self.countdown()
- # 取消暂停
- self.screencapWaitState.set()
-
- def waitScreencap(self):
- """
- 暂停录屏
- :return:
- """
- # 判断录屏状态与倒计时状态
- if self.screencapState and not self.countdownState:
- self.screencapWaitState.clear()
- # 暂停指示
- self.lbNum.set(0)
- # 显示标签
- self.lb.configure(fg="red")
-
- def stopScreencap(self):
- """
- 停止录屏
- :return:
- """
- # 判断录屏状态与倒计时状态
- if self.screencapState and not self.countdownState:
- # 取消暂停
- self.screencapWaitState.set()
- # 录屏状态关闭
- self.screencapState = False
- # 倒计时初始化
- self.lbNum.set(self.lbNumBack)
- # 显示标签
- self.lb.configure(fg="red")
- # 开启缩放
- self.resizable(1, 1)
-
- def countdown(self):
- """
- 倒计时
- :return:
- """
- # 倒计时状态开
- self.countdownState = True
- time.sleep(1)
- while self.lbNum.get() > 1:
- self.lbNum.set(self.lbNum.get() - 1)
- time.sleep(1)
- # 隐藏标签
- self.lb.configure(fg="Crimson")
- # 倒计时状态关
- self.countdownState = False
-
-
- if __name__ == '__main__':
- root = Window()
- root.mainloop()
-