初始化
This commit is contained in:
parent
1741825a55
commit
e0d8d67e9b
@ -1,4 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.12 (ScreenCut)" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (ScreenCut)" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
126
main.py
Normal file
126
main.py
Normal file
@ -0,0 +1,126 @@
|
||||
import pinPicture
|
||||
from PIL import Image
|
||||
import tkinter as tk
|
||||
|
||||
import pyautogui
|
||||
import keyboard
|
||||
|
||||
|
||||
def capture_screen():
|
||||
screenshot = pyautogui.screenshot()
|
||||
root = tk.Tk()
|
||||
image = screenshot.convert('RGBA')
|
||||
pin = pinPicture.PinPicture(image, root)
|
||||
root.mainloop()
|
||||
|
||||
|
||||
|
||||
# 监听特定快捷键,这里假设是Ctrl+Alt+S
|
||||
keyboard.add_hotkey('F7', capture_screen)
|
||||
|
||||
# 保持程序运行,持续监听快捷键
|
||||
keyboard.wait()
|
||||
|
||||
#
|
||||
# from tkinter import Tk, Frame, Canvas, Button
|
||||
# from tkinter.colorchooser import askcolor
|
||||
#
|
||||
#
|
||||
# class Application(Frame):
|
||||
# def __init__(self, master=None):
|
||||
# super().__init__(master)
|
||||
# self.master = master
|
||||
# self.pack()
|
||||
# self.createWidget()
|
||||
# self.x = 0
|
||||
# self.y = 0
|
||||
# self.lastDraw = 0 # 最后绘制的图形id
|
||||
# self.startDrawFlag = False
|
||||
# self.fgcolor = "red"
|
||||
#
|
||||
# def createWidget(self):
|
||||
# # 创建绘图区
|
||||
# self.drawPad = Canvas(root, width=900, height=500, bg="black")
|
||||
# self.drawPad.pack()
|
||||
#
|
||||
# # 画图软件的各种按钮
|
||||
# btn_pen = Button(self, text="画笔", name="pen")
|
||||
# btn_pen.pack(side="left", padx="10")
|
||||
# btn_rect = Button(self, text="矩形", name="rect")
|
||||
# btn_rect.pack(side="left", padx="10")
|
||||
# btn_clear = Button(self, text="清屏", name="clear")
|
||||
# btn_clear.pack(side="left", padx="10")
|
||||
# btn_erasor = Button(self, text="橡皮擦", name="erasor")
|
||||
# btn_erasor.pack(side="left", padx="10")
|
||||
# btn_line = Button(self, text="直线", name="line")
|
||||
# btn_line.pack(side="left", padx="10")
|
||||
# btn_lineArrow = Button(self, text="箭头直线", name="lineArrow")
|
||||
# btn_lineArrow.pack(side="left", padx="10")
|
||||
# btn_color = Button(self, text="颜色", name="color")
|
||||
# btn_color.pack(side="left", padx="10")
|
||||
#
|
||||
# # 为所有button绑定事件
|
||||
# btn_pen.bind_class("Button", "<1>", self.eventManage)
|
||||
# self.drawPad.bind("<ButtonRelease-1>", self.stopDraw)
|
||||
#
|
||||
# def stopDraw(self, event):
|
||||
# self.startDrawFlag = False
|
||||
# self.lastDraw = 0
|
||||
#
|
||||
# def startDraw(self, event):
|
||||
# self.drawPad.delete(self.lastDraw)
|
||||
# if not self.startDrawFlag:
|
||||
# self.startDrawFlag = True
|
||||
# self.x = event.x
|
||||
# self.y = event.y
|
||||
#
|
||||
# def eventManage(self, event):
|
||||
# name = event.widget.winfo_name()
|
||||
# print(name)
|
||||
# if name == "line":
|
||||
# self.drawPad.bind("<B1-Motion>", self.myline)
|
||||
# elif name == "lineArrow":
|
||||
# self.drawPad.bind("<B1-Motion>", self.mylineArrow)
|
||||
# elif name == "rect":
|
||||
# self.drawPad.bind("<B1-Motion>", self.myRect)
|
||||
# elif name == "pen":
|
||||
# self.drawPad.bind("<B1-Motion>", self.myPen)
|
||||
# elif name == "erasor":
|
||||
# self.drawPad.bind("<B1-Motion>", self.myErasor)
|
||||
# elif name == "clear":
|
||||
# self.drawPad.delete("all")
|
||||
# elif name == "color":
|
||||
# c = askcolor(color=self.fgcolor, title="选择画笔颜色")
|
||||
# self.fgcolor = c[1]
|
||||
#
|
||||
# def myline(self, event):
|
||||
# self.startDraw(event)
|
||||
# self.lastDraw = self.drawPad.create_line(self.x, self.y, event.x, event.y, fill=self.fgcolor)
|
||||
#
|
||||
# def mylineArrow(self, event):
|
||||
# self.startDraw(event)
|
||||
# self.lastDraw = self.drawPad.create_line(self.x, self.y, event.x, event.y, arrow=LAST, fill=self.fgcolor)
|
||||
#
|
||||
# def myRect(self, event):
|
||||
# self.startDraw(event)
|
||||
# self.lastDraw = self.drawPad.create_rectangle(self.x, self.y, event.x, event.y, outline=self.fgcolor)
|
||||
#
|
||||
# def myPen(self, event):
|
||||
# self.startDraw(event)
|
||||
# self.drawPad.create_line(self.x, self.y, event.x, event.y, fill=self.fgcolor)
|
||||
# self.x = event.x
|
||||
# self.y = event.y
|
||||
#
|
||||
# def myErasor(self, event):
|
||||
# self.startDraw(event)
|
||||
# self.drawPad.create_rectangle(event.x - 3, event.y - 3, event.x + 3, event.y + 3, fill="black")
|
||||
# self.x = event.x
|
||||
# self.y = event.y
|
||||
#
|
||||
#
|
||||
# if __name__ == '__main__':
|
||||
# root = Tk()
|
||||
# root.geometry("900x500+200+200")
|
||||
# root.title("画图软件")
|
||||
# app = Application(master=root)
|
||||
# root.mainloop()
|
||||
283
pinPicture.py
Normal file
283
pinPicture.py
Normal file
@ -0,0 +1,283 @@
|
||||
import io
|
||||
import math
|
||||
import tkinter as tk
|
||||
import win32clipboard
|
||||
from PIL import Image, ImageTk, ImageChops, ImageDraw, ImageGrab
|
||||
import threading
|
||||
|
||||
|
||||
class PinPicture(tk.Frame):
|
||||
def __init__(self, image, master=None):
|
||||
super().__init__(master)
|
||||
self.lineBtn = None
|
||||
self.arrowBtn = None
|
||||
self.rectBtn = None
|
||||
self.penBtn = None
|
||||
self.drawModeBtn = None
|
||||
self.scale_factor = 1.0
|
||||
self.photo = None
|
||||
self.canvas = None
|
||||
self.master = master
|
||||
self.pad = Image.new('RGBA', image.size)
|
||||
self.drawPad = ImageDraw.Draw(self.pad)
|
||||
self.pack()
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
self.penX = 0
|
||||
self.penY = 0
|
||||
self.penX1 = 0
|
||||
self.penY1 = 0
|
||||
self.cutX = 0
|
||||
self.cutY = 0
|
||||
self.lastDraw = 0
|
||||
self.drawing = False
|
||||
self.drawMode = False
|
||||
self.color = "red"
|
||||
self.image = image
|
||||
if image.mode != "RGBA":
|
||||
image = image.convert("RGBA")
|
||||
self.create_window()
|
||||
self.penWidth = 3
|
||||
self.arrowSize = 10
|
||||
|
||||
# 创建窗口
|
||||
def create_window(self):
|
||||
self.master.overrideredirect(True)
|
||||
self.master.attributes('-transparentcolor', 'white')
|
||||
self.master.config(bg='white')
|
||||
self.master.attributes('-topmost', True)
|
||||
self.canvas = tk.Canvas(self.master, height=self.image.height, width=self.image.width)
|
||||
self.penBtn = tk.Button(text='笔', command=self.set_pen)
|
||||
self.rectBtn = tk.Button(text='矩形', command=self.set_rect)
|
||||
self.arrowBtn = tk.Button(text='箭头', command=self.set_arrow)
|
||||
self.lineBtn = tk.Button(text='直线', command=self.set_line)
|
||||
|
||||
self.master.bind("<Escape>", self.close)
|
||||
self.master.bind("<Enter>", self.enter_canvas)
|
||||
self.master.bind("<Leave>", self.leave)
|
||||
self.photo = ImageTk.PhotoImage(Image.alpha_composite(self.image, self.pad))
|
||||
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)
|
||||
self.canvas.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
|
||||
self.canvas.bind("<ButtonPress-3>", self.close)
|
||||
self.canvas.bind("<ButtonRelease-1>", self.stop_draw)
|
||||
self.canvas.bind("<Return>", self.on_save)
|
||||
|
||||
self.cut_mode_event()
|
||||
|
||||
def on_save(self, event):
|
||||
output = io.BytesIO()
|
||||
self.image.convert("RGB").save(output, "BMP")
|
||||
data = output.getvalue()[14:] # BMP 文件头前14字节
|
||||
output.close()
|
||||
win32clipboard.OpenClipboard()
|
||||
try:
|
||||
win32clipboard.EmptyClipboard()
|
||||
win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
|
||||
finally:
|
||||
win32clipboard.CloseClipboard()
|
||||
|
||||
def cut_mode_event(self):
|
||||
self.canvas.bind("<ButtonPress-1>", self.on_cut_start)
|
||||
self.canvas.bind("<B1-Motion>", self.on_cut)
|
||||
self.canvas.bind("<ButtonPress-3>", self.on_copy)
|
||||
self.canvas.unbind("<MouseWheel>")
|
||||
self.pad = Image.new('RGBA', self.image.size, color=(0, 0, 0, 100))
|
||||
self.drawPad = ImageDraw.Draw(self.pad)
|
||||
|
||||
def on_copy(self, event):
|
||||
self.x = self.penX
|
||||
self.y = self.penY
|
||||
self.image = self.image.crop((self.penX, self.penY, self.cutX, self.cutY))
|
||||
self.pad = Image.new('RGBA', self.image.size)
|
||||
self.drawPad = ImageDraw.Draw(self.pad)
|
||||
self.update_canvas()
|
||||
self.master.geometry(f"+{self.x}+{self.y}")
|
||||
self.pin_mode_event()
|
||||
self.canvas.bind("<ButtonPress-3>", self.close)
|
||||
|
||||
def pin_mode_event(self):
|
||||
self.canvas.bind("<ButtonPress-1>", self.on_drag_start)
|
||||
self.canvas.bind("<B1-Motion>", self.on_drag)
|
||||
self.canvas.bind("<MouseWheel>", self.on_mouse_wheel)
|
||||
|
||||
# 鼠标进入
|
||||
def enter_canvas(self, event):
|
||||
self.canvas.focus_set()
|
||||
if self.drawModeBtn is None and not self.drawMode:
|
||||
self.drawModeBtn = tk.Button(text="编辑", command=self.draw_mode_event)
|
||||
self.drawModeBtn.pack(side=tk.TOP, expand=True)
|
||||
elif not self.drawMode:
|
||||
self.drawModeBtn.pack(side=tk.TOP, expand=True)
|
||||
|
||||
# 鼠标离开
|
||||
def leave(self, event):
|
||||
if self.drawModeBtn is not None and not self.drawMode:
|
||||
self.drawModeBtn.pack_forget()
|
||||
|
||||
# 进入编辑模式
|
||||
def draw_mode_event(self):
|
||||
self.drawMode = True
|
||||
self.drawModeBtn.pack_forget()
|
||||
self.canvas.bind("<B1-Motion>", self.pen)
|
||||
self.penBtn.pack()
|
||||
self.rectBtn.pack()
|
||||
self.arrowBtn.pack()
|
||||
self.lineBtn.pack()
|
||||
|
||||
def set_pen(self):
|
||||
self.canvas.bind("<B1-Motion>", self.pen)
|
||||
|
||||
def set_rect(self):
|
||||
self.canvas.bind("<B1-Motion>", self.rect)
|
||||
|
||||
def set_arrow(self):
|
||||
self.canvas.bind("<B1-Motion>", self.arrow)
|
||||
|
||||
def set_line(self):
|
||||
self.canvas.bind("<B1-Motion>", self.line)
|
||||
|
||||
# 拖动图片设置窗口坐标
|
||||
def on_drag(self, event):
|
||||
delta_x = event.x - self.x
|
||||
delta_y = event.y - self.y
|
||||
new_x = self.master.winfo_x() + delta_x
|
||||
new_y = self.master.winfo_y() + delta_y
|
||||
self.master.geometry(f"+{new_x}+{new_y}")
|
||||
|
||||
def on_cut(self, event):
|
||||
self.start_draw(event)
|
||||
self.pad = Image.new('RGBA', self.image.size, color=(0, 0, 0, 100))
|
||||
self.drawPad = ImageDraw.Draw(self.pad)
|
||||
self.drawPad.rectangle((self.penX, self.penY, event.x, event.y), fill=(0,0,0,0), outline="purple")
|
||||
self.update_canvas_cut()
|
||||
self.cutX = event.x
|
||||
self.cutY = event.y
|
||||
|
||||
# 记录开始拖动的坐标
|
||||
def on_drag_start(self, event):
|
||||
self.x = event.x
|
||||
self.y = event.y
|
||||
|
||||
def on_cut_start(self, event):
|
||||
self.pad = Image.new('RGBA', self.image.size, color=(0, 0, 0, 100))
|
||||
self.drawPad = ImageDraw.Draw(self.pad)
|
||||
self.penX = event.x
|
||||
self.penY = event.y
|
||||
# 关闭窗口
|
||||
def close(self, event):
|
||||
self.master.destroy()
|
||||
|
||||
# 滚轮调整大小
|
||||
def on_mouse_wheel(self, event):
|
||||
if self.drawMode:
|
||||
if event.delta > 0:
|
||||
self.penWidth += 1
|
||||
self.arrowSize += 1
|
||||
else:
|
||||
self.penWidth -= 1
|
||||
self.arrowSize -= 1
|
||||
else:
|
||||
if event.delta > 0:
|
||||
self.scale_factor *= 1.1
|
||||
else:
|
||||
self.scale_factor /= 1.1
|
||||
self.update_canvas()
|
||||
|
||||
def update_canvas(self):
|
||||
new_width = int(self.image.width * self.scale_factor)
|
||||
new_height = int(self.image.height * self.scale_factor)
|
||||
image = Image.alpha_composite(self.image, self.pad)
|
||||
image = image.resize((new_width, new_height))
|
||||
self.photo = ImageTk.PhotoImage(image)
|
||||
self.canvas.config(width=new_width, height=new_height)
|
||||
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)
|
||||
|
||||
def update_canvas_cut(self):
|
||||
new_width = int(self.image.width * self.scale_factor)
|
||||
new_height = int(self.image.height * self.scale_factor)
|
||||
image1 = Image.alpha_composite(self.image, self.pad)
|
||||
image1 = image1.resize((new_width, new_height))
|
||||
self.photo = ImageTk.PhotoImage(image1)
|
||||
self.canvas.config(width=new_width, height=new_height)
|
||||
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)
|
||||
|
||||
def start_draw(self, event):
|
||||
if not self.drawing:
|
||||
self.drawing = True
|
||||
self.penX = event.x
|
||||
self.penY = event.y
|
||||
self.penY1 = event.y
|
||||
self.penX1 = event.x
|
||||
|
||||
def pen(self, event):
|
||||
self.start_draw(event)
|
||||
self.drawPad.line(self.point_convert(self.penX, self.penY, event.x, event.y), self.color, width=self.penWidth)
|
||||
self.drawPad.line(self.point_convert(self.penX1, self.penY1, event.x, event.y), self.color, width=self.penWidth)
|
||||
self.penX1 = self.penX
|
||||
self.penY1 = self.penY
|
||||
self.penX = event.x
|
||||
self.penY = event.y
|
||||
self.update_canvas()
|
||||
|
||||
def line(self, event):
|
||||
self.start_draw(event)
|
||||
self.pad = Image.new('RGBA', self.image.size)
|
||||
self.drawPad = ImageDraw.Draw(self.pad)
|
||||
self.drawPad.line(self.point_convert(self.penX, self.penY, event.x, event.y), self.color, width=self.penWidth)
|
||||
self.update_canvas()
|
||||
|
||||
def rect(self, event):
|
||||
self.start_draw(event)
|
||||
self.pad = Image.new('RGBA', self.image.size)
|
||||
self.drawPad = ImageDraw.Draw(self.pad)
|
||||
self.drawPad.line(self.point_convert(self.penX, self.penY, self.penX, event.y), self.color, width=self.penWidth)
|
||||
self.drawPad.line(self.point_convert(self.penX, self.penY, event.x, self.penY), self.color, width=self.penWidth)
|
||||
self.drawPad.line(self.point_convert(event.x, self.penY, event.x, event.y), self.color, width=self.penWidth)
|
||||
self.drawPad.line(self.point_convert(self.penX, event.y, event.x, event.y), self.color, width=self.penWidth)
|
||||
self.update_canvas()
|
||||
|
||||
def arrow(self, event):
|
||||
self.start_draw(event)
|
||||
self.pad = Image.new('RGBA', self.image.size)
|
||||
self.drawPad = ImageDraw.Draw(self.pad)
|
||||
pos = self.point_convert(self.penX, self.penY, event.x, event.y)
|
||||
self.drawPad.line(pos, self.color, width=self.penWidth)
|
||||
|
||||
x1 = pos[0]
|
||||
y1 = pos[1]
|
||||
x2 = pos[2]
|
||||
y2 = pos[3]
|
||||
l = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
|
||||
cosa = (x2 - x1) / l
|
||||
sina = (y2 - y1) / l
|
||||
k = sina / cosa
|
||||
d = self.arrowSize * (sina + cosa)
|
||||
if (sina < cosa):
|
||||
xa = x2 - d
|
||||
ya = y2 + math.sqrt(2 * self.arrowSize * self.arrowSize - d * d)
|
||||
xb = x2 - math.sqrt(2 * self.arrowSize * self.arrowSize - d * d)
|
||||
yb = y2 - d
|
||||
else:
|
||||
xa = x2 - d
|
||||
ya = y2 - math.sqrt(2 * self.arrowSize * self.arrowSize - d * d)
|
||||
xb = x2 + math.sqrt(2 * self.arrowSize * self.arrowSize - d * d)
|
||||
yb = y2 - d
|
||||
|
||||
self.drawPad.polygon(
|
||||
((xa, ya), (xb, yb), (pos[2], pos[3])),
|
||||
fill=self.color, outline=(0, 0, 0, 0))
|
||||
self.update_canvas()
|
||||
|
||||
def point_convert(self, x, y, x1, y1):
|
||||
real_x = int(x / self.scale_factor)
|
||||
real_y = int(y / self.scale_factor)
|
||||
real_x1 = int(x1 / self.scale_factor)
|
||||
real_y1 = int(y1 / self.scale_factor)
|
||||
return real_x, real_y, real_x1, real_y1
|
||||
|
||||
def stop_draw(self, event):
|
||||
self.drawing = False
|
||||
if self.drawMode:
|
||||
self.image = Image.alpha_composite(self.image, self.pad)
|
||||
self.pad = Image.new('RGBA', self.image.size)
|
||||
self.drawPad = ImageDraw.Draw(self.pad)
|
||||
BIN
requirements.txt
Normal file
BIN
requirements.txt
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user