前言
毕设有一部分要用到类似QQ截图的功能,这里记录制作过程。因为后期要添加人工智能的功能,所以用python来写桌面应用。
一、需求分析
可以简单的将过程分为以下三步:
点击按钮或敲击快捷键进入截图模式;在截图模式通过鼠标左键按压/松开选取矩形区域;将矩形区域截图保存到指定目录或者剪贴板。
现在我将从第三步开始一步步向上搜索、编写、验证。
二、截图
通过对“python”和“截图”两个关键字搜索不难发现python有多种满足我们需求的函数,这里选用PIL库的grab()函数。time函数是用来测试截图速度的。
from PIL import ImageGrab
import time
# 截取图像
def catch_area(left, top, right, bottom):
return ImageGrab.grab((left, top, right, bottom))
# 测试函数
def test():
first = time.time()
catch_area(101,101,200,300).save('D:/1.jpg')
print(time.time() - first)
test()
三、矩形选择
截图函数需要四个参数,即矩形区域的上下左右的坐标。为了获取这四个参数我们需要监听鼠标的点击事件。我本来想搜寻一个全局监听器的api的,这里选用的是pyhook。但是测试发现不支持python2.7,而python3.7的安装过程极其复杂,故放弃此方法。
后来我想到可以利用GUI生成一个全屏的button,然后监听对这个button的点击事件。这里的GUI选用wxPython,3.7版本直接pip安装。
import wx
from PIL import ImageGrab
class ScreenShot(wx.Frame):
left,right,top,bottom = 0,0,0,0
img = None
def __init__(self, parent):
wx.Frame.__init__(self, parent,
style = wx.MAXIMIZE # 全屏显示
)
# 设置背景色
self.SetBackgroundColour((255,255,255))
# 设置透明度
self.SetTransparent(30)
# 注册事件
self.Bind(wx.EVT_LEFT_DOWN, self.OnDown, self)
self.Bind(wx.EVT_LEFT_UP, self.OnUp, self)
# 显示button
self.Show(True)
def OnDown(self, event):
pos = event.GetPosition()
self.top = pos.y
self.left = pos.x
def OnUp(self, event):
pos = event.GetPosition()
self.bottom = pos.y
self.right = pos.x
print(self.left, self.top, self.right, self.bottom)
self.img = self.catch_area(
self.left, self.top, self.right, self.bottom)
# 截图完毕后关闭button
self.Close(False)
def catch_area(self, left, top, right, bottom):
return ImageGrab.grab((left, top, right, bottom))
# 测试用例
# app = wx.App(False)
# frame = ScreenShot(None)
# app.MainLoop()
这里只是将截得图像存在img变量中,至于后续操作请各位自行实现。
四、按钮设置
最后需要构造一个按钮并为其设置快捷键/热键。GUI同样使用之前的wxPython。页面就随便写写;设置快捷键即为某个控件绑定键盘事件,需要将焦点聚集到某个控件上;而热键是可以全局使用,热键设置可将事件绑定到菜单选项上,也可以直接注册。这里直接注册热键。
import wx
import ScreenShot as SS
class MainWindow(wx.Frame):
def __init__(self, parent):
# 视窗属性
wx.Frame.__init__(self, parent,
size = (1000, 200), # 视窗大小
style = wx.CLIP_CHILDREN, # 视窗样式,这个样式可以去掉原生的栏
#pos = (200, 200) # 视窗位置,下面设置居中了
)
# 创建位于窗口的底部的状态栏
self.CreateStatusBar()
# 布局
self.root = wx.BoxSizer(wx.VERTICAL)
self.menu = wx.BoxSizer(wx.HORIZONTAL)
self.body = wx.BoxSizer(wx.VERTICAL)
self.menuText = [u"开始截图", u"退出"]
self.menubuttons = []
for i in range(0, 2):
# 新建按键
self.menubuttons.append(wx.Button(self, -1, self.menuText[i]))
self.menu.Add(self.menubuttons[i], 1, wx.SHAPED)
# 新建只读文本框(预留)
self.control = wx.TextCtrl(self, style = wx.TE_READONLY)
self.body.Add(self.control, 1, wx.GROW)
self.root.Add(self.menu, 1, wx.GROW)
self.root.Add(self.body, 4, wx.EXPAND)
# 激活布局
self.SetSizer(self.root)
self.SetAutoLayout(True)
# self.root.Fit(self) # 适应内部大小
# 事件注册
self.Bind(wx.EVT_BUTTON, self.OnStart, self.menubuttons[0])
self.Bind(wx.EVT_BUTTON, self.OnExit, self.menubuttons[1])
# 热键注册
self.hotkey = wx.NewIdRef() # 创建id
self.RegisterHotKey(self.hotkey, wx.MOD_CONTROL, ord('Q')) # 注册热键(按ctrl+Q键响应)
self.Bind(wx.EVT_HOTKEY, self.OnKeyBoard, id=self.hotkey) # 绑定热键事件
# 窗口居中
self.Center()
# 显示视窗
self.Show(True)
# 开始截图
def OnStart(self, event):
SS.ScreenShot(self)
# 关闭整个应用
def OnExit(self, event):
self.Destroy()
# 热键事件
def OnKeyBoard(self, event):
SS.ScreenShot(self)
app = wx.App(False)
frame = MainWindow(None)
app.MainLoop()
总结
最后两个代码块就是完整应用。这只是一个十分粗略的应用,很多细节都没有优化,比如最小化到托盘、选取区域时自动标出区域。若各位有能力可自行实现。到此这篇关于Python实现一个简单的QQ截图的文章就介绍到这了,更多相关python QQ截图内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!