-
Notifications
You must be signed in to change notification settings - Fork 4
/
screenshot.py
166 lines (135 loc) · 6.07 KB
/
screenshot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
from PySide6.QtWidgets import QWidget, QApplication
from PySide6.QtCore import Qt, QPoint, QRect, Signal
from PySide6.QtGui import QPainter, QColor, QPen, QPixmap, QScreen
import os
from datetime import datetime
class ScreenshotOverlay(QWidget):
screenshot_taken = Signal(str)
def __init__(self):
super().__init__()
self.start_pos = None
self.end_pos = None
self.is_drawing = False
self.background = None
# 设置全屏无边框窗口
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool)
self.setAttribute(Qt.WA_TranslucentBackground)
# 获取主屏幕
self.screen = QApplication.primaryScreen()
# 获取设备像素比
self.device_pixel_ratio = self.screen.devicePixelRatio()
# 获取主屏幕大小(使用实际像素大小)
screen_geometry = self.screen.geometry()
self.setGeometry(screen_geometry)
# 确保tmp目录存在
if not os.path.exists('tmp'):
os.makedirs('tmp')
def showEvent(self, event):
"""窗口显示时捕获整个屏幕"""
if not self.background:
# 使用grabWindow替代
window_id = 0 # 0 表示整个屏幕
screen_geometry = self.screen.geometry()
self.background = self.screen.grabWindow(
window_id,
screen_geometry.x(),
screen_geometry.y(),
screen_geometry.width(),
screen_geometry.height()
)
# 设置设备像素比
self.background.setDevicePixelRatio(self.device_pixel_ratio)
super().showEvent(event)
def paintEvent(self, event):
painter = QPainter(self)
# 绘制半透明遮罩
painter.fillRect(self.rect(), QColor(0, 0, 0, 100))
if self.start_pos and self.end_pos and self.is_drawing:
# 计算选区
rect = self.get_selection_rect()
# 绘制选区内的实际截图内容
if self.background:
# 考虑设备像素比进行坐标转换
scaled_rect = QRect(
int(rect.x() * self.device_pixel_ratio),
int(rect.y() * self.device_pixel_ratio),
int(rect.width() * self.device_pixel_ratio),
int(rect.height() * self.device_pixel_ratio)
)
# 使用缩放后的矩形从背景图中获取内容,但绘制到原始大小的矩形中
painter.drawPixmap(rect, self.background, scaled_rect)
# 绘制选区边框
pen = QPen(QColor(0, 174, 255), 2)
painter.setPen(pen)
painter.drawRect(rect)
# 显示选区大小
size_text = f"{rect.width()} × {rect.height()}"
text_rect = painter.boundingRect(rect, Qt.AlignCenter, size_text)
# 在选区上方绘制尺寸信息
text_y = rect.top() - 25 if rect.top() > 25 else rect.bottom() + 25
text_x = rect.center().x() - text_rect.width() / 2
# 绘制文本背景
text_bg_rect = text_rect.adjusted(-5, -5, 5, 5)
text_bg_rect.moveCenter(QPoint(rect.center().x(), text_y))
painter.fillRect(text_bg_rect, QColor(0, 0, 0, 160))
# 绘制文本
painter.setPen(QColor(255, 255, 255))
painter.drawText(text_bg_rect, Qt.AlignCenter, size_text)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.start_pos = event.pos()
self.is_drawing = True
def mouseMoveEvent(self, event):
if self.is_drawing:
self.end_pos = event.pos()
self.update()
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton and self.is_drawing:
self.end_pos = event.pos()
self.is_drawing = False
# 保存截图
rect = self.get_selection_rect()
if rect.width() > 10 and rect.height() > 10:
self.save_screenshot(rect)
self.hide()
self.start_pos = None
self.end_pos = None
self.background = None
def keyPressEvent(self, event):
if event.key() == Qt.Key_Escape:
self.hide()
self.start_pos = None
self.end_pos = None
self.is_drawing = False
self.background = None
def get_selection_rect(self):
if not self.start_pos or not self.end_pos:
return QRect()
return QRect(
min(self.start_pos.x(), self.end_pos.x()),
min(self.start_pos.y(), self.end_pos.y()),
abs(self.end_pos.x() - self.start_pos.x()),
abs(self.end_pos.y() - self.start_pos.y())
)
def save_screenshot(self, rect):
"""保存截图到tmp文件夹"""
try:
if self.background:
# 考虑设备像素比进行坐标转换
scaled_rect = QRect(
int(rect.x() * self.device_pixel_ratio),
int(rect.y() * self.device_pixel_ratio),
int(rect.width() * self.device_pixel_ratio),
int(rect.height() * self.device_pixel_ratio)
)
# 从背景图中截取选定区域
cropped = self.background.copy(scaled_rect)
# 生成文件名
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"tmp/screenshot_{timestamp}.png"
# 保存图片
cropped.save(filename)
# 发送保存的文件路径
self.screenshot_taken.emit(filename)
except Exception as e:
print(f"保存截图失败: {str(e)}")