好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Python Tkiner 写的截图小工具 实现了大部分基础功能

最近在写一些小工具,因为是给别人用的需要界面,刚开始使用pyQT5? 功能强大,但是打包后一个小工具 就有几十兆 有点蛋疼而且还很消耗资源;后面改用TK,TK明显简洁很多,功能同样也若很多!

因为有截图需求,就抽空写了这个工具,全当练习。过程当中遇到过好多蛋疼的事情,功能基本实现后发出来给大家分享一下,我个人还是比较喜欢python这门语言的!

实现思路:

3.1.新建一个最小化窗口,利用线程启动监听"ctrl+a"启动截图窗口

3.2.截图窗口初始化时利用? pyautogui.screenshot 截取全屏(类似PRTSC)作为子窗口的背景(在这搞了好久,后面没办法只有利用canvas设置背景),子窗口最大化取消菜单栏

3.3.在主窗口上的canvas上用绑定鼠标事件,根据鼠标选取截图范围,和鼠标操作相关功能

3.4.保存功能是根据截图范围重新截图生成文件保存

代码

main_UI.py
tkinter.messagebox?showinfo
Sc_Tool.Sc_Win?*
keyboard
_thread

():
????showinfo(,?)

scwd?=?win?=?Tk()
win.wm_state()
win.iconify()

():
????scwd
????scwd?=?windSc(win)
????scwd.newwind()
():
????()
????scwd.exit_sc(scwd)
():
????keyboard.add_hotkey(,?star_sc,?=(),=?)
():
????keyboard.add_hotkey(,?exit_sc,?=(),=?)

:
????_thread.start_new_thread(startThread1,?())
????_thread.start_new_thread(startThread2,?())
e:
????(e)
win.mainloop()

():
????showinfo(,?)

scwd?=?win?=?Tk()
win.wm_state()
win.iconify()
():
????scwd
????scwd?=?windSc(win)
????scwd.newwind()
():
????scwd.exit_sc(scwd)
():
????scwd.ctrl_z(scwd)

():
????keyboard.add_hotkey(,?star_sc,?=(),=?)
():
????keyboard.add_hotkey(,?exit_sc,?=(),=?)
():
????keyboard.add_hotkey(,?ctrl_z,?=(),?=?)

:
????_thread.start_new_thread(startThread1,?())
????_thread.start_new_thread(startThread2,?())
????_thread.start_new_thread(startThread3,?())

e:
????(e)
win.mainloop()
Sc_Tool/Sc_Win.py
import?os
from?tkinter?import?*
import?tkinter
import?pyautogui?as?pyautogui
from?PIL?import?Image,?ImageTk
import?tkinter.font?as?tkFont
import?time

class?windSc:
????win,?file_path,im,?winAppSc,?mouEvent,?canvas?=?None,?None,?None,?None,?None,?None
????#窗口宽??窗口高??宽??高???截图起点x坐标??截图起点y坐标??绘图起点x坐标?绘图起点?y坐标
????win_w,?win_h,?width,?height,?x,?y,?dx,?dy=?0,?0,?0,?0,?0,?0,?0,?0
????#截图结束点坐标
????end_x,?end_y?=?0,?0
????#开始添加图形的起始坐标
????cr_x,?cr_y?=0,?0
????#记录按钮的状态、文本输入按钮状态
????but1_stat,but_text_stat?=?False,?False
????#记录按钮类型??1矩形?2圆形
????but_type?=?0
????#tag标记?文本输入单击次数标记
????i,p?=?1?,0
????#?工具栏部件
????but1,?but2,?but3,?but4,?buttext,text_lable?=?None,?None,?None,?None,?None,?None
????#?画笔大小,文本框行数
????size,?row?=?1,?1
????#?画笔颜色
????color?=?"black"
????#?字体
????font?=?None
????#?按钮图片
????img1,?img2,?img3,?imgs,?imgp1,?imgp2,?imgp3?=?None,?None,?None,?None,?None,?None,?None
????imgred?,?imgwhite?,?imgblack,?imgblue,?imggreen,?imgyellow,?imgback?=?None,?None,?None,?None,?None,?None,?None
????#?工具按钮列表
????but_list?=?[]
????#?图形id列表
????ids?=?[]

????def?__init__(self,win):
????????self.win?=?win
????????#?获取屏幕分辨率
????????self.width,?self.height?=?win.winfo_screenwidth(),?win.winfo_screenheight()
????????#?窗口宽度和高度
????????self.win_w,?self.win_h?=?self.width,?self.height
????????image?=?pyautogui.screenshot(region=[0,?0,?self.width,?self.height]).resize((self.width,?self.height))
????????self.im?=?ImageTk.PhotoImage(image)
????????self.img1?=?tkinter.PhotoImage(file="Sc_Tool/icon/1.png")
????????self.img2?=?tkinter.PhotoImage(file="Sc_Tool/icon/2.png")
????????self.img3?=?tkinter.PhotoImage(file="Sc_Tool/icon/3.png")
????????self.imgtext?=?tkinter.PhotoImage(file="Sc_Tool/icon/Text.png")
????????self.imgs?=?tkinter.PhotoImage(file="Sc_Tool/icon/s.png")
????????self.imgp1?=?tkinter.PhotoImage(file="Sc_Tool/icon/p1.png")
????????self.imgp2?=?tkinter.PhotoImage(file="Sc_Tool/icon/p2.png")
????????self.imgp3?=?tkinter.PhotoImage(file="Sc_Tool/icon/p3.png")
????????self.imgblack?=?tkinter.PhotoImage(file="Sc_Tool/icon/black.png")
????????self.imgwhite?=?tkinter.PhotoImage(file="Sc_Tool/icon/white.png")
????????self.imgred?=?tkinter.PhotoImage(file="Sc_Tool/icon/red.png")
????????self.imggreen?=?tkinter.PhotoImage(file="Sc_Tool/icon/green.png")
????????self.imgblue?=?tkinter.PhotoImage(file="Sc_Tool/icon/blue.png")
????????self.imgyellow?=?tkinter.PhotoImage(file="Sc_Tool/icon/yellow.png")
????????self.imgback?=?tkinter.PhotoImage(file="Sc_Tool/icon/b.png")

????def?newwind(self,event=''):
????????#?最小化主窗口
????????self.win.wm_state('icon')
????????self.win.iconify()
????????self.winAppSc?=?Toplevel(self.win)
????????#winAppSc.attributes("-alpha",?1)
????????#删除标题栏
????????self.winAppSc.overrideredirect(True)
????????self.winAppSc.geometry("%dx%d+%d+%d"?%(self.win_w,self.win_h,(self.width-self.win_w)/2,(self.height-self.win_h)/2))
????????self.winAppSc.config(bg="white")
????????self.winAppSc.title('截屏')
????????self.winAppSc.attributes("-topmost",?True)

????????canvas?=?tkinter.Canvas(self.winAppSc,
????????????????????????????????width=self.win_w,??#?指定Canvas组件的宽度
????????????????????????????????height=self.win_h,??#?指定Canvas组件的高度
????????????????????????????????bg='red')??#?指定Canvas组件的背景色

????????canvas.create_image(0,?0,?image=self.im,?anchor='nw',?tag=('r',?'r0'))
????????canvas.pack(fill='both',?expand='yes')
????????self.canvas?=?canvas

????????#工具栏部件
????????self.but1?=?Button(self.winAppSc,?text="保存",?image=self.imgs)
????????self.but2?=?Button(self.winAppSc,?text="矩形",?image=self.img1)
????????self.but3?=?Button(self.winAppSc,?text="圆形",?image=self.img2)
????????self.but4?=?Button(self.winAppSc,?text="箭头",?image=self.img3)
????????self.buttext?=?Button(self.winAppSc,?text="文本",?image=self.imgtext)
????????self.but5?=?Button(self.winAppSc,?text="返回",?image=self.imgback)

????????#?画笔大小
????????self.sizebut1?=??Button(self.winAppSc,?text="1",?image?=?self.imgp1)
????????self.sizebut2?=?Button(self.winAppSc,?text="5",?image?=?self.imgp2)
????????self.sizebut3?=?Button(self.winAppSc,?text="10",?image?=?self.imgp3)

????????#?画笔颜色
????????self.color_red?=?Button(self.winAppSc,?text="red",?image?=?self.imgred)
????????self.color_green?=?Button(self.winAppSc,?text="red",?image=self.imggreen)
????????self.color_blue?=?Button(self.winAppSc,?text="red",?image=self.imgblue)
????????self.color_yellow?=?Button(self.winAppSc,?text="red",?image=self.imgyellow)
????????self.color_black?=?Button(self.winAppSc,?text="red",?image=self.imgblack)
????????self.color_white?=?Button(self.winAppSc,?text="red",?image=self.imgwhite)

????????#文本框
????????self.text_entry?=?Text(self.winAppSc,bg=None,relief=None,height=self.row,width=4)

????????canvas.bind('<1>',?lambda?event:self.setxy(event,canvas))
????????canvas.bind('<B1-Motion>',lambda?event:self.getxy(event,canvas))
????????canvas.bind('<ButtonRelease-1>',?lambda?event:?self.setBtn(event,self.winAppSc))
????????canvas.bind('<3>',?lambda?event:?self.clear(canvas))
????????self.but1.bind('<1>',?lambda?event:?self.bu_save(event))
????????self.but2.bind('<1>',?lambda?event:?self.bu_click(event,canvas,1))
????????self.but3.bind('<1>',?lambda?event:?self.bu_click(event,?canvas,2))
????????self.but4.bind('<1>',?lambda?event:?self.bu_click(event,?canvas,3))
????????self.buttext.bind('<1>',?lambda?event:?self.bu_click_text(event,?canvas))
????????self.sizebut1.bind('<1>',?lambda?event:?self.sizebut_click(1))
????????self.sizebut2.bind('<1>',?lambda?event:?self.sizebut_click(5))
????????self.sizebut3.bind('<1>',?lambda?event:?self.sizebut_click(10))
????????self.color_red.bind('<1>',?lambda?event:?self.colorbut_click("red"))
????????self.color_green.bind('<1>',?lambda?event:?self.colorbut_click("green"))
????????self.color_blue.bind('<1>',?lambda?event:?self.colorbut_click("blue"))
????????self.color_yellow.bind('<1>',?lambda?event:?self.colorbut_click("yellow"))
????????self.color_white.bind('<1>',?lambda?event:?self.colorbut_click("white"))
????????self.color_black.bind('<1>',?lambda?event:?self.colorbut_click("black"))
????????self.text_entry.bind('<Key>',lambda?event:?self.entry(event))
????????self.but5.bind('<1>',?lambda?event:?self.ctrl_z())

????????#?先清空but_list?以防止下次截图时?还保存有之前的按钮??而之前的按钮的父窗口已经销毁
????????self.but_list.clear()
????????self.but_list.append(self.but1)
????????self.but_list.append(self.but2)
????????self.but_list.append(self.but3)
????????self.but_list.append(self.but4)
????????self.but_list.append(self.buttext)
????????self.but_list.append(self.sizebut1)
????????self.but_list.append(self.sizebut2)
????????self.but_list.append(self.sizebut3)
????????self.but_list.append(self.color_red)
????????self.but_list.append(self.color_green)
????????self.but_list.append(self.color_blue)
????????self.but_list.append(self.color_yellow)
????????self.but_list.append(self.color_white)
????????self.but_list.append(self.color_black)
????????self.but_list.append(self.but5)

????#?鼠标点击调用初始化绘制截图的起点位置
????def?setxy(self,event,canvas):
????????#清空上一次鼠标事件,并设置截图的起始位置
????????self.mouEvent?=?None
????????if?(self.but1_stat):
????????????#如果超出截图区域改变起始坐标为截图起始坐标
????????????if?(event.x?>?self.x?and?event.x?<?self.end_x):
????????????????self.dx?=?event.x
????????????if?(event.y?>?self.y?and?event.y?<?self.end_y):
????????????????self.dy?=?event.y
????????else:
????????????self.x,?self.y=event.x,?event.y
????????????for?but?in?self.but_list:
????????????????but.place_forget()
????????????canvas.delete(self,?'j0')
????????#文本输入操作
????????if?(self.but_text_stat?and?self.but_type?==?4):
????????????self.p?=?self.p?+?1
????????????if(?self.p%2?==?1):
????????????????self.text_entry.delete('1.0',?'end')
????????????????self.font?=?tkFont.Font(family='宋体',?size=(self.size+5)*3)
????????????????self.text_entry.config(?font=self.font,fg=self.color,width=4?,height=1)
????????????????self.text_entry.place(x=event.x,?y=event.y)
????????????else:
????????????????canvas.create_text(self.text_entry.winfo_x(),self.text_entry.winfo_y()+15,text=self.text_entry.get(1.0,?END),font=self.font,justify?=?LEFT,fill=self.color,anchor=?W)
????????????????self.text_entry.place_forget()
????????????#?获取所有图形对象
????????self.ids?=?list(canvas.find_all())

????def?PreventOutOfBounds(self,eventx,eventy):
????????if?(eventx?<?self.x):
????????????eventx?=?self.x
????????elif?(eventx?>?self.end_x):
????????????eventx?=?self.end_x
????????if?(eventy?<?self.y):
????????????eventy?=?self.y
????????elif?(eventy?>?self.end_y):
????????????eventy?=?self.end_y
????????return?eventx,eventy

????#?鼠标按下左键拖动时调用绘制截图的终点位置
????def?getxy(self,event,canvas):
????????#?记录上一次的鼠标事件?,?如果按钮有按下不消除选取框矩形??没有按钮按下消除上一个选取矩形
????????if?(self.but1_stat):
????????????if?self.but_type?==?1:
????????????????#?销毁上一个鼠标暂停点绘制的图形
????????????????canvas.delete(self,?"j%d"?%(self.i))
????????????????#?防止图形画出界
????????????????event.x,?event.y?=?self.PreventOutOfBounds(event.x,event.y)
????????????????canvas.create_rectangle(self.dx,self.dy,event.x,event.y,width=self.size,outline=self.color,tag?=?('j',"j%d"?%(self.i)))
????????????elif?self.but_type?==?2:
????????????????canvas.delete(self,?"j%d"?%?(self.i))
????????????????event.x,?event.y?=?self.PreventOutOfBounds(event.x,?event.y)
????????????????canvas.create_oval(self.dx,self.dy,event.x,event.y,width=self.size,outline=self.color,tag?=?('j',"j%d"?%(self.i)))
????????????elif?self.but_type?==?3:
????????????????canvas.delete(self,?"j%d"?%?(self.i))
????????????????event.x,?event.y?=?self.PreventOutOfBounds(event.x,?event.y)
????????????????canvas.create_line(self.dx,self.dy,event.x,event.y,width=self.size,fill=self.color,arrow=tkinter.LAST,tag?=?('j',"j%d"?%(self.i)))
????????else:
????????????#新截图框
????????????#print("销毁截图矩形")
????????????self.mouEvent?=?event
????????????#?删除上一个矩形
????????????canvas.delete(self,"j0")
????????????#?绘制新矩形?并设置结束点坐标
????????????canvas.create_rectangle(self.x,self.y,event.x,event.y,tag?=?('j','j0'))
????????????self.end_x,?self.end_y?=?event.x,?event.y
????????self.ids?=?list(canvas.find_all())

????#?鼠标释放的时候绘制工具按钮??如果上次释放鼠标左键的上一个鼠标事件是拖动<B1-Motion>?则显示按钮
????def?setBtn(self,event,winAppSc):
????????#?获取截图区域大小?如果长宽小于5个像素则不显示按钮
????????w,?h?=?event.x?-?self.x,?event.y?-?self.y
????????if?(self.mouEvent?!=?None?and?w?>?5?and?h?>?5):
????????????x,?y?=?self.x,?event.y
????????????for?but?in?self.but_list:
????????????????but.place(x=x,y=y)
????????????????x=?x+35
????????#释放鼠标新的图形动作tags标记变更
????????self.i?=?self.i?+?1

????def?bu_click(self,event,canvas,but_name):
????????#?按钮按下记录其状态为True
????????self.but1_stat?=?True
????????self.i?=?self.i?+?1
????????self.but_type?=?but_name
????????#清除文本框
????????self.text_entry.place_forget()

????#按下鼠标右键取消截图初始化参数
????def?clear(self,canvas):
????????#print("取消截图")
????????self.i?=?1
????????self.but1_stat?=?False
????????#销毁所有对象
????????canvas.delete(ALL)
????????#从新加载IMG对象,此时依旧是之前的截图背景
????????canvas.create_image(0,?0,?image=self.im,?anchor='nw',?tag=('r',?'r0'))
????????canvas.pack(fill='both',?expand='yes')
????????#?隐藏按钮?删除截图框
????????for?but?in?self.but_list:
????????????but.place_forget()
????#?设置画笔大小
????def?sizebut_click(self,size):
????????self.but1_stat?=?True
????????self.size?=?size
????????self.font?=?tkFont.Font(family='宋体',?size=(self.size?+?5)?*?3)
????????self.text_entry.config(font?=?self.font)

????#?设置画笔颜色
????def?colorbut_click(self,?color):
????????self.but1_stat?=?True
????????self.color?=?color
????????self.text_entry.config(fg=self.color)
????#?退出窗口
????def?exit_sc(self,scwd):
????????try:
????????????scwd.winAppSc.destroy()
????????except?Exception?as?e:
????????????print(e)

????def?bu_click_text(self,?event,?canvas):
????????#?输入文本框
????????self.but1_stat?=?True
????????self.but_text_stat?=?True
????????self.but_type?=?4

????def?entry(self,event):
????????keysym?=??event.keysym
????????if?keysym?==?"Return":
????????????self.row?=?self.row?+?1
????????????self.text_entry.config(height=self.row)
????????elif?keysym?==?"BackSpace":
????????????text?=?self.text_entry.get("%d.0"?%?(self.row),?"%d.end"?%?(self.row))
????????????if?len(text)?==?0:
????????????????self.row?=?self.row?-?1
????????????????if?self.row?<?1:
????????????????????self.row?=?1
????????????self.text_entry.config(height=self.row)
????????else:
????????????tmp?=?0
????????????for?i?in?range(1,?self.row?+?1):
????????????????pattern?=?"[\u4e00-\u9fa5]+"
????????????????regex?=?re测试数据pile(pattern)
????????????????text?=?self.text_entry.get("%d.0"?%?(i),?"%d.end"?%?(i))
????????????????ch?=?regex.findall(text)
????????????????chstr?=?''.join(ch)
????????????????text_len?=?len(text)?+?len(chstr)
????????????????if?text_len?>=?tmp:?tmp?=?text_len
????????????if?(tmp?>=?2):?self.text_entry.config(width=tmp?+?3)

????def?bu_save(self,?event):
????????image?=?pyautogui.screenshot(region=[self.x+1,?self.y+1,?self.end_x-self.x-1,?self.end_y-self.y-1])
????????save_dir?=?"save"
????????if?not?os.path.exists(save_dir):
????????????os.makedirs(save_dir)
????????t?=?int(time.time())
????????image.save("%s/%d.jpg"?%(save_dir,t))
????????#?截图完成销毁窗口
????????self.winAppSc.destroy()

????def?ctrl_z(self):
????????if?len(self.ids)?>?2:
????????????self.canvas.delete(self.ids[-1])
????????????self.ids.pop()

截图

源码因为打包了python环境比较大

链接:https://pan.baidu测试数据/s/1hND-HARBPt6mumgnvvUtqA?

提取码:WLWL?

查看更多关于Python Tkiner 写的截图小工具 实现了大部分基础功能的详细内容...

  阅读:49次