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('', lambda event:self.setxy(event,canvas))
canvas.bind('',lambda event:self.getxy(event,canvas))
canvas.bind('', lambda event: self.setBtn(event,self.winAppSc))
canvas.bind('', lambda event: self.clear(canvas))
self.but1.bind('', lambda event: self.bu_save(event))
self.but2.bind('', lambda event: self.bu_click(event,canvas,1))
self.but3.bind('', lambda event: self.bu_click(event, canvas,2))
self.but4.bind('', lambda event: self.bu_click(event, canvas,3))
self.buttext.bind('', lambda event: self.bu_click_text(event, canvas))
self.sizebut1.bind('', lambda event: self.sizebut_click(1))
self.sizebut2.bind('', lambda event: self.sizebut_click(5))
self.sizebut3.bind('', lambda event: self.sizebut_click(10))
self.color_red.bind('', lambda event: self.colorbut_click("red"))
self.color_green.bind('', lambda event: self.colorbut_click("green"))
self.color_blue.bind('', lambda event: self.colorbut_click("blue"))
self.color_yellow.bind('', lambda event: self.colorbut_click("yellow"))
self.color_white.bind('', lambda event: self.colorbut_click("white"))
self.color_black.bind('', lambda event: self.colorbut_click("black"))
self.text_entry.bind('',lambda event: self.entry(event))
self.but5.bind('', 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())
# 鼠标释放的时候绘制工具按钮 如果上次释放鼠标左键的上一个鼠标事件是拖动 则显示按钮
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.compile(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()