From e0d8d67e9b51ae65275cb84ec3f26689a54f63e8 Mon Sep 17 00:00:00 2001 From: awinx Date: Wed, 15 Jan 2025 20:08:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/misc.xml | 3 + main.py | 126 +++++++++++++++++++++ pinPicture.py | 283 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | Bin 0 -> 408 bytes 4 files changed, 412 insertions(+) create mode 100644 main.py create mode 100644 pinPicture.py create mode 100644 requirements.txt diff --git a/.idea/misc.xml b/.idea/misc.xml index 0259c84..e8141ec 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,7 @@ + + \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..4607527 --- /dev/null +++ b/main.py @@ -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("", 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("", self.myline) +# elif name == "lineArrow": +# self.drawPad.bind("", self.mylineArrow) +# elif name == "rect": +# self.drawPad.bind("", self.myRect) +# elif name == "pen": +# self.drawPad.bind("", self.myPen) +# elif name == "erasor": +# self.drawPad.bind("", 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() \ No newline at end of file diff --git a/pinPicture.py b/pinPicture.py new file mode 100644 index 0000000..7b7edd0 --- /dev/null +++ b/pinPicture.py @@ -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("", self.close) + self.master.bind("", self.enter_canvas) + self.master.bind("", 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("", self.close) + self.canvas.bind("", self.stop_draw) + self.canvas.bind("", 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("", self.on_cut_start) + self.canvas.bind("", self.on_cut) + self.canvas.bind("", self.on_copy) + self.canvas.unbind("") + 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("", self.close) + + def pin_mode_event(self): + self.canvas.bind("", self.on_drag_start) + self.canvas.bind("", self.on_drag) + self.canvas.bind("", 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("", self.pen) + self.penBtn.pack() + self.rectBtn.pack() + self.arrowBtn.pack() + self.lineBtn.pack() + + def set_pen(self): + self.canvas.bind("", self.pen) + + def set_rect(self): + self.canvas.bind("", self.rect) + + def set_arrow(self): + self.canvas.bind("", self.arrow) + + def set_line(self): + self.canvas.bind("", 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) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..50a268b45b8616857e787f7d5858aee0880d95f9 GIT binary patch literal 408 zcmY+AK?{N~9L3)`=&Ov>f;@Dni*yj8h|XmuVyKv5_Tj7dpKU9~#>V^Yy|=wz1yb}l zp~4Xj&RB3vpx`0kI>Q(v#8mINkzAw1g(pWTa>CTeapkDcY1N~HxG1`bzG2FeE-i@& zdpa49Q0Gi76)~s9fqo_X7(eMGGqhaHMj2Kl9^b@YqGn!Arv?dI<=ji2^pQN*X-g(y zo@wL%sXJ;7i4;#x<1qZs@amp-J57|jab_v!BwaeK2Jp2Wu)$ovq(xz~-EVyWCb>E+ literal 0 HcmV?d00001