Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
PaddleOCR
提交
322b4150
P
PaddleOCR
项目概览
PaddlePaddle
/
PaddleOCR
大约 1 年 前同步成功
通知
1528
Star
32962
Fork
6643
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
108
列表
看板
标记
里程碑
合并请求
7
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PaddleOCR
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
108
Issue
108
列表
看板
标记
里程碑
合并请求
7
合并请求
7
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
322b4150
编写于
8月 24, 2022
作者:
E
Evezerest
提交者:
GitHub
8月 24, 2022
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Delete ScreenShotWidget.py
上级
22ad94aa
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
0 addition
and
1108 deletion
+0
-1108
ScreenShotWidget.py
ScreenShotWidget.py
+0
-1108
未找到文件。
ScreenShotWidget.py
已删除
100644 → 0
浏览文件 @
22ad94aa
# coding=utf-8
# author: fardeas
# from: https://blog.csdn.net/u010501845/article/details/124931326
import
os
import
sys
from
datetime
import
datetime
from
qtpy
import
QtCore
,
QtGui
from
qtpy.QtWidgets
import
*
from
qtpy.QtCore
import
*
from
qtpy.QtGui
import
*
class
TextInputWidget
(
QTextEdit
):
'''在截图区域内的文本输入框'''
def
__init__
(
self
,
god
=
None
):
super
().
__init__
(
god
)
self
.
god
=
god
# 设置背景透明
# self.setStyleSheet("QTextEdit{background-color: transparent;}")
palette
=
self
.
palette
()
palette
.
setBrush
(
QtGui
.
QPalette
.
ColorRole
.
Base
,
self
.
god
.
color_transparent
)
self
.
setPalette
(
palette
)
self
.
setTextColor
(
self
.
god
.
toolbar
.
curColor
())
self
.
setCurrentFont
(
self
.
god
.
toolbar
.
curFont
())
self
.
_doc
=
self
.
document
()
# QTextDocument
self
.
textChanged
.
connect
(
self
.
adjustSizeByContent
)
self
.
adjustSizeByContent
()
# 初始化调整高度为一行
self
.
hide
()
def
adjustSizeByContent
(
self
,
margin
=
30
):
'''限制宽度不超出截图区域,根据文本内容调整高度,不会出现滚动条'''
self
.
_doc
.
setTextWidth
(
self
.
viewport
().
width
())
margins
=
self
.
contentsMargins
()
h
=
int
(
self
.
_doc
.
size
().
height
()
+
margins
.
top
()
+
margins
.
bottom
())
self
.
setFixedHeight
(
h
)
def
beginNewInput
(
self
,
pos
,
endPointF
):
'''开始新的文本输入'''
self
.
_maxRect
=
self
.
god
.
screenArea
.
normalizeRectF
(
pos
,
endPointF
)
self
.
waitForInput
()
def
waitForInput
(
self
):
self
.
setGeometry
(
self
.
_maxRect
.
toRect
())
# self.setGeometry(self._maxRect.adjusted(0, 0, -1, 0)) # 宽度-1
self
.
setFocus
()
self
.
show
()
def
loadTextInputBy
(
self
,
action
):
'''载入修改旧的文本
action:(type, color, font, rectf, txt)'''
self
.
setTextColor
(
action
[
1
])
self
.
setCurrentFont
(
action
[
2
])
self
.
_maxRect
=
action
[
3
]
self
.
append
(
action
[
4
])
self
.
god
.
isDrawing
=
True
self
.
waitForInput
()
class
LineWidthAction
(
QAction
):
'''画笔粗细选择器'''
def
__init__
(
self
,
text
,
parent
,
lineWidth
):
super
().
__init__
(
text
,
parent
)
self
.
_lineWidth
=
lineWidth
self
.
refresh
(
QtCore
.
Qt
.
GlobalColor
.
red
)
self
.
triggered
.
connect
(
self
.
onTriggered
)
self
.
setVisible
(
False
)
def
refresh
(
self
,
color
):
painter
=
self
.
parent
().
god
.
screenArea
.
_painter
dotRadius
=
QPointF
(
self
.
_lineWidth
,
self
.
_lineWidth
)
centerPoint
=
self
.
parent
().
iconPixmapCenter
()
pixmap
=
self
.
parent
().
iconPixmapCopy
()
painter
.
begin
(
pixmap
)
painter
.
setPen
(
self
.
parent
().
god
.
pen_transparent
)
painter
.
setBrush
(
color
)
painter
.
drawEllipse
(
QRectF
(
centerPoint
-
dotRadius
,
centerPoint
+
dotRadius
))
painter
.
end
()
self
.
setIcon
(
QIcon
(
pixmap
))
def
onTriggered
(
self
):
self
.
parent
().
_curLineWidth
=
self
.
_lineWidth
class
FontAction
(
QAction
):
'''字体选择器'''
def
__init__
(
self
,
text
,
parent
):
super
().
__init__
(
text
,
parent
)
self
.
setIcon
(
QIcon
(
r
"img/sys/font.png"
))
self
.
_curFont
=
self
.
parent
().
god
.
font_textInput
self
.
triggered
.
connect
(
self
.
onTriggered
)
self
.
setVisible
(
False
)
def
onTriggered
(
self
):
font
,
ok
=
QFontDialog
.
getFont
(
self
.
_curFont
,
self
.
parent
(),
caption
=
'选择字体'
)
if
ok
:
self
.
_curFont
=
font
self
.
parent
().
god
.
textInputWg
.
setCurrentFont
(
font
)
class
ColorAction
(
QAction
):
'''颜色选择器'''
def
__init__
(
self
,
text
,
parent
):
super
().
__init__
(
text
,
parent
)
self
.
_curColor
=
QtCore
.
Qt
.
GlobalColor
.
red
self
.
_pixmap
=
QPixmap
(
32
,
32
)
self
.
refresh
(
self
.
_curColor
)
self
.
triggered
.
connect
(
self
.
onTriggered
)
def
refresh
(
self
,
color
):
self
.
_curColor
=
color
self
.
_pixmap
.
fill
(
color
)
self
.
setIcon
(
QIcon
(
self
.
_pixmap
))
self
.
parent
().
_at_line_small
.
refresh
(
color
)
self
.
parent
().
_at_line_normal
.
refresh
(
color
)
self
.
parent
().
_at_line_big
.
refresh
(
color
)
def
onTriggered
(
self
):
col
=
QColorDialog
.
getColor
(
self
.
_curColor
,
self
.
parent
(),
title
=
'选择颜色'
)
if
col
.
isValid
():
self
.
refresh
(
col
)
self
.
parent
().
god
.
textInputWg
.
setTextColor
(
col
)
class
ScreenShotToolBar
(
QToolBar
):
'''截图区域工具条'''
def
__init__
(
self
,
god
):
super
().
__init__
(
god
)
self
.
god
=
god
self
.
setToolButtonStyle
(
QtCore
.
Qt
.
ToolButtonStyle
.
ToolButtonTextUnderIcon
)
self
.
setStyleSheet
(
"QToolBar {border-radius: 5px;padding: 3px;background-color: #eeeeef;}"
)
self
.
_style_normal
=
"QToolBar QToolButton{color: black;}"
self
.
_style_selected
=
"QToolBar QToolButton{color: #ff7300;border: 1px solid #BEDAF2;background-color: #D6E4F1}"
# 与鼠标悬停样式一样
self
.
_iconPixmap
=
QPixmap
(
32
,
32
)
self
.
_iconPixmap
.
fill
(
self
.
god
.
color_transparent
)
self
.
_iconPixmapCenter
=
QPointF
(
self
.
_iconPixmap
.
rect
().
center
())
self
.
_curLineWidth
=
3
self
.
_at_line_small
=
LineWidthAction
(
'细'
,
self
,
self
.
_curLineWidth
-
2
)
self
.
_at_line_normal
=
LineWidthAction
(
'中'
,
self
,
self
.
_curLineWidth
)
self
.
_at_line_big
=
LineWidthAction
(
'粗'
,
self
,
self
.
_curLineWidth
+
2
)
self
.
_at_font
=
FontAction
(
'字体'
,
self
)
self
.
_at_color
=
ColorAction
(
'颜色'
,
self
)
# self._at_rectangle = QAction(QIcon(r"img/sys/rectangle.png"), '矩形', self, triggered=self.beforeDrawRectangle)
# self._at_ellipse = QAction(QIcon(r"img/sys/ellipse.png"), '椭圆', self, triggered=self.beforeDrawEllipse)
# self._at_graffiti = QAction(QIcon(r"img/sys/graffiti.png"), '涂鸦', self, triggered=self.beforeDrawGraffiti)
# self._at_textInput = QAction(QIcon(r"img/sys/write.png"), '文字', self, triggered=self.beforeDrawText)
# self.addAction(self._at_line_small)
# self.addAction(self._at_line_normal)
# self.addAction(self._at_line_big)
# self.addAction(self._at_font)
# self.addAction(self._at_color)
# self.addSeparator()
# self.addAction(self._at_rectangle)
# self.addAction(self._at_ellipse)
# self.addAction(self._at_graffiti)
# self.addAction(self._at_textInput)
# self.addAction(QAction(QIcon(r"img/sys/undo.png"), '撤销', self, triggered=self.undo))
# self.addSeparator()
self
.
addAction
(
QAction
(
QApplication
.
style
().
standardIcon
(
40
),
'退出'
,
self
,
triggered
=
self
.
god
.
rejectSlot
))
self
.
addAction
(
QAction
(
QApplication
.
style
().
standardIcon
(
45
),
'接受'
,
self
,
triggered
=
self
.
god
.
acceptSlot
))
# self.addAction(QAction(QIcon(r"img/chat/download.png"), '保存', self, triggered=lambda: self.beforeSave('local')))
# self.addAction(QAction(QIcon(r"img/chat/sendImg.png"), '复制', self, triggered=lambda: self.beforeSave('clipboard')))
# self.actionTriggered.connect(self.onActionTriggered)
def
curLineWidth
(
self
):
return
self
.
_curLineWidth
def
curFont
(
self
):
return
self
.
_at_font
.
_curFont
def
curColor
(
self
):
return
self
.
_at_color
.
_curColor
# return QColor(self._at_color._curColor.toRgb()) # 颜色的副本
def
iconPixmapCopy
(
self
):
return
self
.
_iconPixmap
.
copy
()
def
iconPixmapCenter
(
self
):
return
self
.
_iconPixmapCenter
# def onActionTriggered(self, action):
# '''突出显示已选中的画笔粗细、编辑模式'''
# for at in [self._at_line_small, self._at_line_normal, self._at_line_big]:
# if at._lineWidth == self._curLineWidth:
# self.widgetForAction(at).setStyleSheet(self._style_selected)
# else:
# self.widgetForAction(at).setStyleSheet(self._style_normal)
# if self.god.isDrawRectangle:
# self.widgetForAction(self._at_rectangle).setStyleSheet(self._style_selected)
# else:
# self.widgetForAction(self._at_rectangle).setStyleSheet(self._style_normal)
# if self.god.isDrawEllipse:
# self.widgetForAction(self._at_ellipse).setStyleSheet(self._style_selected)
# else:
# self.widgetForAction(self._at_ellipse).setStyleSheet(self._style_normal)
# if self.god.isDrawGraffiti:
# self.widgetForAction(self._at_graffiti).setStyleSheet(self._style_selected)
# else:
# self.widgetForAction(self._at_graffiti).setStyleSheet(self._style_normal)
# if self.god.isDrawText:
# self.widgetForAction(self._at_textInput).setStyleSheet(self._style_selected)
# else:
# self.widgetForAction(self._at_textInput).setStyleSheet(self._style_normal)
def
setLineWidthActionVisible
(
self
,
flag
):
self
.
_at_line_small
.
setVisible
(
flag
)
self
.
_at_line_normal
.
setVisible
(
flag
)
self
.
_at_line_big
.
setVisible
(
flag
)
def
beforeDrawRectangle
(
self
):
self
.
god
.
clearEditFlags
()
self
.
god
.
isDrawRectangle
=
True
self
.
setLineWidthActionVisible
(
True
)
self
.
_at_font
.
setVisible
(
False
)
def
beforeDrawEllipse
(
self
):
self
.
god
.
clearEditFlags
()
self
.
god
.
isDrawEllipse
=
True
self
.
setLineWidthActionVisible
(
True
)
self
.
_at_font
.
setVisible
(
False
)
def
beforeDrawGraffiti
(
self
):
self
.
god
.
clearEditFlags
()
self
.
god
.
isDrawGraffiti
=
True
self
.
setLineWidthActionVisible
(
True
)
self
.
_at_font
.
setVisible
(
False
)
def
beforeDrawText
(
self
):
self
.
god
.
clearEditFlags
()
self
.
god
.
isDrawText
=
True
self
.
setLineWidthActionVisible
(
False
)
self
.
_at_font
.
setVisible
(
True
)
def
undo
(
self
):
'''撤销上次编辑行为'''
if
self
.
god
.
screenArea
.
undoEditAction
():
self
.
god
.
update
()
def
beforeSave
(
self
,
target
):
# 若正在编辑文本未保存,先完成编辑
if
self
.
god
.
isDrawing
and
self
.
god
.
isDrawText
:
self
.
god
.
screenArea
.
saveTextInputAction
()
if
target
==
'local'
:
self
.
god
.
save2Local
()
elif
target
==
'clipboard'
:
self
.
god
.
save2Clipboard
()
def
enterEvent
(
self
,
event
):
self
.
god
.
setCursor
(
QtCore
.
Qt
.
CursorShape
.
ArrowCursor
)
# 工具条上显示标准箭头cursor
def
leaveEvent
(
self
,
event
):
self
.
god
.
setCursor
(
QtCore
.
Qt
.
CursorShape
.
CrossCursor
)
# 十字无箭头
class
ScreenArea
(
QtCore
.
QObject
):
'''屏幕区域(提供各种算法的核心类),划分为9个子区域:
TopLeft,Top,TopRight
Left,Center,Right
BottomLeft,Bottom,BottomRight
其中Center根据start、end两个QPointF确定
'''
def
__init__
(
self
,
god
):
super
().
__init__
()
self
.
god
=
god
self
.
_pt_start
=
QPointF
()
# 划定截图区域时鼠标左键按下的位置(topLeft)
self
.
_pt_end
=
QPointF
()
# 划定截图区域时鼠标左键松开的位置(bottomRight)
self
.
_rt_toolbar
=
QRectF
()
# 工具条的矩形
self
.
_actions
=
[]
# 在截图区域上的所有编辑行为(矩形、椭圆、涂鸦、文本输入等)
self
.
_pt_startEdit
=
QPointF
()
# 在截图区域上绘制矩形、椭圆时鼠标左键按下的位置(topLeft)
self
.
_pt_endEdit
=
QPointF
()
# 在截图区域上绘制矩形、椭圆时鼠标左键松开的位置(bottomRight)
self
.
_pointfs
=
[]
# 涂鸦经过的所有点
self
.
_painter
=
QPainter
()
# 独立于ScreenShotWidget之外的画家类
self
.
_textOption
=
QtGui
.
QTextOption
(
QtCore
.
Qt
.
AlignmentFlag
.
AlignLeft
|
QtCore
.
Qt
.
AlignmentFlag
.
AlignTop
)
self
.
_textOption
.
setWrapMode
(
QtGui
.
QTextOption
.
WrapMode
.
WrapAnywhere
)
# 文本在矩形内自动换行
# self._textOption.setWrapMode(QtGui.QTextOption.WrapMode.WrapAtWordBoundaryOrAnywhere)
self
.
captureScreen
()
def
captureScreen
(
self
):
'''抓取整个屏幕的截图'''
# screen = QtGui.QGuiApplication.primaryScreen()
self
.
_screenPixmap
=
QApplication
.
primaryScreen
().
grabWindow
(
0
)
self
.
_pixelRatio
=
self
.
_screenPixmap
.
devicePixelRatio
()
# 设备像素比
self
.
_rt_screen
=
self
.
screenLogicalRectF
()
self
.
remakeNightArea
()
def
normalizeRectF
(
self
,
topLeftPoint
,
bottomRightPoint
):
'''根据起止点生成宽高非负数的QRectF,通常用于bottomRightPoint比topLeftPoint更左更上的情况
入参可以是QPoint或QPointF'''
rectf
=
QRectF
(
topLeftPoint
,
bottomRightPoint
)
x
=
rectf
.
x
()
y
=
rectf
.
y
()
w
=
rectf
.
width
()
h
=
rectf
.
height
()
if
w
<
0
:
# bottomRightPoint在topLeftPoint左侧时,topLeftPoint往左移动
x
=
x
+
w
w
=
-
w
if
h
<
0
:
# bottomRightPoint在topLeftPoint上侧时,topLeftPoint往上移动
y
=
y
+
h
h
=
-
h
return
QRectF
(
x
,
y
,
w
,
h
)
def
physicalRectF
(
self
,
rectf
):
'''计算划定的截图区域的(缩放倍率1.0的)原始矩形(会变大)
rectf:划定的截图区域的矩形。可为QRect或QRectF'''
return
QRectF
(
rectf
.
x
()
*
self
.
_pixelRatio
,
rectf
.
y
()
*
self
.
_pixelRatio
,
rectf
.
width
()
*
self
.
_pixelRatio
,
rectf
.
height
()
*
self
.
_pixelRatio
)
def
logicalRectF
(
self
,
physicalRectF
):
'''根据原始矩形计算缩放后的矩形(会变小)
physicalRectF:缩放倍率1.0的原始矩形。可为QRect或QRectF'''
return
QRectF
(
physicalRectF
.
x
()
/
self
.
_pixelRatio
,
physicalRectF
.
y
()
/
self
.
_pixelRatio
,
physicalRectF
.
width
()
/
self
.
_pixelRatio
,
physicalRectF
.
height
()
/
self
.
_pixelRatio
)
def
physicalPixmap
(
self
,
rectf
,
editAction
=
False
):
'''根据指定区域获取其原始大小的(缩放倍率1.0的)QPixmap
rectf:指定区域。可为QRect或QRectF
editAction:是否带上编辑结果'''
if
editAction
:
canvasPixmap
=
self
.
screenPhysicalPixmapCopy
()
self
.
_painter
.
begin
(
canvasPixmap
)
self
.
paintEachEditAction
(
self
.
_painter
,
textBorder
=
False
)
self
.
_painter
.
end
()
return
canvasPixmap
.
copy
(
self
.
physicalRectF
(
rectf
).
toRect
())
else
:
return
self
.
_screenPixmap
.
copy
(
self
.
physicalRectF
(
rectf
).
toRect
())
def
screenPhysicalRectF
(
self
):
return
QRectF
(
self
.
_screenPixmap
.
rect
())
def
screenLogicalRectF
(
self
):
return
QRectF
(
QPointF
(
0
,
0
),
self
.
screenLogicalSizeF
())
# 即当前屏幕显示的大小
def
screenPhysicalSizeF
(
self
):
return
QSizeF
(
self
.
_screenPixmap
.
size
())
def
screenLogicalSizeF
(
self
):
return
QSizeF
(
self
.
_screenPixmap
.
width
()
/
self
.
_pixelRatio
,
self
.
_screenPixmap
.
height
()
/
self
.
_pixelRatio
)
def
screenPhysicalPixmapCopy
(
self
):
return
self
.
_screenPixmap
.
copy
()
def
screenLogicalPixmapCopy
(
self
):
return
self
.
_screenPixmap
.
scaled
(
self
.
screenLogicalSizeF
().
toSize
())
def
centerPhysicalRectF
(
self
):
return
self
.
physicalRectF
(
self
.
_rt_center
)
def
centerLogicalRectF
(
self
):
'''根据屏幕上的start、end两个QPointF确定'''
return
self
.
_rt_center
def
centerPhysicalPixmap
(
self
,
editAction
=
True
):
'''截图区域的QPixmap
editAction:是否带上编辑结果'''
return
self
.
physicalPixmap
(
self
.
_rt_center
+
QMarginsF
(
-
1
,
-
1
,
1
,
1
),
editAction
=
editAction
)
def
centerTopMid
(
self
):
return
self
.
_pt_centerTopMid
def
centerBottomMid
(
self
):
return
self
.
_pt_centerBottomMid
def
centerLeftMid
(
self
):
return
self
.
_pt_centerLeftMid
def
centerRightMid
(
self
):
return
self
.
_pt_centerRightMid
def
setStartPoint
(
self
,
pointf
,
remake
=
False
):
self
.
_pt_start
=
pointf
if
remake
:
self
.
remakeNightArea
()
def
setEndPoint
(
self
,
pointf
,
remake
=
False
):
self
.
_pt_end
=
pointf
if
remake
:
self
.
remakeNightArea
()
def
setCenterArea
(
self
,
start
,
end
):
self
.
_pt_start
=
start
self
.
_pt_end
=
end
self
.
remakeNightArea
()
def
remakeNightArea
(
self
):
'''重新划分九宫格区域。根据中央截图区域计算出来的其他8个区域、截图区域四个边框中点坐标等都是logical的'''
self
.
_rt_center
=
self
.
normalizeRectF
(
self
.
_pt_start
,
self
.
_pt_end
)
# 中央区域上下左右边框的中点,用于调整大小
self
.
_pt_centerTopMid
=
(
self
.
_rt_center
.
topLeft
()
+
self
.
_rt_center
.
topRight
())
/
2
self
.
_pt_centerBottomMid
=
(
self
.
_rt_center
.
bottomLeft
()
+
self
.
_rt_center
.
bottomRight
())
/
2
self
.
_pt_centerLeftMid
=
(
self
.
_rt_center
.
topLeft
()
+
self
.
_rt_center
.
bottomLeft
())
/
2
self
.
_pt_centerRightMid
=
(
self
.
_rt_center
.
topRight
()
+
self
.
_rt_center
.
bottomRight
())
/
2
# 以截图区域左上、上中、右上、左中、右中、左下、下中、右下为中心的正方形区域,用于调整大小
self
.
_square_topLeft
=
self
.
squareAreaByCenter
(
self
.
_rt_center
.
topLeft
())
self
.
_square_topRight
=
self
.
squareAreaByCenter
(
self
.
_rt_center
.
topRight
())
self
.
_square_bottomLeft
=
self
.
squareAreaByCenter
(
self
.
_rt_center
.
bottomLeft
())
self
.
_square_bottomRight
=
self
.
squareAreaByCenter
(
self
.
_rt_center
.
bottomRight
())
self
.
_square_topMid
=
self
.
squareAreaByCenter
(
self
.
_pt_centerTopMid
)
self
.
_square_bottomMid
=
self
.
squareAreaByCenter
(
self
.
_pt_centerBottomMid
)
self
.
_square_leftMid
=
self
.
squareAreaByCenter
(
self
.
_pt_centerLeftMid
)
self
.
_square_rightMid
=
self
.
squareAreaByCenter
(
self
.
_pt_centerRightMid
)
# 除中央截图区域外的8个区域
self
.
_rt_topLeft
=
QRectF
(
self
.
_rt_screen
.
topLeft
(),
self
.
_rt_center
.
topLeft
())
self
.
_rt_top
=
QRectF
(
QPointF
(
self
.
_rt_center
.
topLeft
().
x
(),
0
),
self
.
_rt_center
.
topRight
())
self
.
_rt_topRight
=
QRectF
(
QPointF
(
self
.
_rt_center
.
topRight
().
x
(),
0
),
QPointF
(
self
.
_rt_screen
.
width
(),
self
.
_rt_center
.
topRight
().
y
()))
self
.
_rt_left
=
QRectF
(
QPointF
(
0
,
self
.
_rt_center
.
topLeft
().
y
()),
self
.
_rt_center
.
bottomLeft
())
self
.
_rt_right
=
QRectF
(
self
.
_rt_center
.
topRight
(),
QPointF
(
self
.
_rt_screen
.
width
(),
self
.
_rt_center
.
bottomRight
().
y
()))
self
.
_rt_bottomLeft
=
QRectF
(
QPointF
(
0
,
self
.
_rt_center
.
bottomLeft
().
y
()),
QPointF
(
self
.
_rt_center
.
bottomLeft
().
x
(),
self
.
_rt_screen
.
height
()))
self
.
_rt_bottom
=
QRectF
(
self
.
_rt_center
.
bottomLeft
(),
QPointF
(
self
.
_rt_center
.
bottomRight
().
x
(),
self
.
_rt_screen
.
height
()))
self
.
_rt_bottomRight
=
QRectF
(
self
.
_rt_center
.
bottomRight
(),
self
.
_rt_screen
.
bottomRight
())
def
squareAreaByCenter
(
self
,
pointf
):
'''以QPointF为中心的正方形QRectF'''
rectf
=
QRectF
(
0
,
0
,
15
,
15
)
rectf
.
moveCenter
(
pointf
)
return
rectf
def
aroundAreaIn8Direction
(
self
):
'''中央区域周边的8个方向的区域(无交集)'''
return
[
self
.
_rt_topLeft
,
self
.
_rt_top
,
self
.
_rt_topRight
,
self
.
_rt_left
,
self
.
_rt_right
,
self
.
_rt_bottomLeft
,
self
.
_rt_bottom
,
self
.
_rt_bottomRight
]
def
aroundAreaIn4Direction
(
self
):
'''中央区域周边的4个方向的区域(有交集)
上区域(左上、上、右上):0, 0, maxX, topRight.y
下区域(左下、下、右下):0, bottomLeft.y, maxX, maxY-bottomLeft.y
左区域(左上、左、左下):0, 0, bottomLeft.x, maxY
右区域(右上、右、右下):topRight.x, 0, maxX - topRight.x, maxY'''
screenSizeF
=
self
.
screenLogicalSizeF
()
pt_topRight
=
self
.
_rt_center
.
topRight
()
pt_bottomLeft
=
self
.
_rt_center
.
bottomLeft
()
return
[
QRectF
(
0
,
0
,
screenSizeF
.
width
(),
pt_topRight
.
y
()),
QRectF
(
0
,
pt_bottomLeft
.
y
(),
screenSizeF
.
width
(),
screenSizeF
.
height
()
-
pt_bottomLeft
.
y
()),
QRectF
(
0
,
0
,
pt_bottomLeft
.
x
(),
screenSizeF
.
height
()),
QRectF
(
pt_topRight
.
x
(),
0
,
screenSizeF
.
width
()
-
pt_topRight
.
x
(),
screenSizeF
.
height
())]
def
aroundAreaWithoutIntersection
(
self
):
'''中央区域周边的4个方向的区域(无交集)
上区域(左上、上、右上):0, 0, maxX, topRight.y
下区域(左下、下、右下):0, bottomLeft.y, maxX, maxY-bottomLeft.y
左区域(左):0, topRight.y, bottomLeft.x-1, center.height
右区域(右):topRight.x+1, topRight.y, maxX - topRight.x, center.height'''
screenSizeF
=
self
.
screenLogicalSizeF
()
pt_topRight
=
self
.
_rt_center
.
topRight
()
pt_bottomLeft
=
self
.
_rt_center
.
bottomLeft
()
centerHeight
=
pt_bottomLeft
.
y
()
-
pt_topRight
.
y
()
return
[
QRectF
(
0
,
0
,
screenSizeF
.
width
(),
pt_topRight
.
y
()),
QRectF
(
0
,
pt_bottomLeft
.
y
(),
screenSizeF
.
width
(),
screenSizeF
.
height
()
-
pt_bottomLeft
.
y
()),
QRectF
(
0
,
pt_topRight
.
y
(),
pt_bottomLeft
.
x
()
-
1
,
centerHeight
),
QRectF
(
pt_topRight
.
x
()
+
1
,
pt_topRight
.
y
(),
screenSizeF
.
width
()
-
pt_topRight
.
x
(),
centerHeight
)]
def
setBeginDragPoint
(
self
,
pointf
):
'''计算开始拖拽位置距离截图区域左上角的向量'''
self
.
_drag_vector
=
pointf
-
self
.
_rt_center
.
topLeft
()
def
getNewPosAfterDrag
(
self
,
pointf
):
'''计算拖拽后截图区域左上角的新位置'''
return
pointf
-
self
.
_drag_vector
def
moveCenterAreaTo
(
self
,
pointf
):
'''限制拖拽不能超出屏幕范围'''
self
.
_rt_center
.
moveTo
(
self
.
getNewPosAfterDrag
(
pointf
))
startPointF
=
self
.
_rt_center
.
topLeft
()
if
startPointF
.
x
()
<
0
:
self
.
_rt_center
.
moveTo
(
0
,
startPointF
.
y
())
startPointF
=
self
.
_rt_center
.
topLeft
()
if
startPointF
.
y
()
<
0
:
self
.
_rt_center
.
moveTo
(
startPointF
.
x
(),
0
)
screenSizeF
=
self
.
screenLogicalSizeF
()
endPointF
=
self
.
_rt_center
.
bottomRight
()
if
endPointF
.
x
()
>
screenSizeF
.
width
():
self
.
_rt_center
.
moveBottomRight
(
QPointF
(
screenSizeF
.
width
(),
endPointF
.
y
()))
endPointF
=
self
.
_rt_center
.
bottomRight
()
if
endPointF
.
y
()
>
screenSizeF
.
height
():
self
.
_rt_center
.
moveBottomRight
(
QPointF
(
endPointF
.
x
(),
screenSizeF
.
height
()))
self
.
setCenterArea
(
self
.
_rt_center
.
topLeft
(),
self
.
_rt_center
.
bottomRight
())
def
setBeginAdjustPoint
(
self
,
pointf
):
'''判断开始调整截图区域大小时鼠标左键在哪个区(不可能是中央区域),用于判断调整大小的意图方向'''
self
.
_mousePos
=
self
.
getMousePosBy
(
pointf
)
def
getMousePosBy
(
self
,
pointf
):
if
self
.
_square_topLeft
.
contains
(
pointf
):
return
'TL'
elif
self
.
_square_topMid
.
contains
(
pointf
):
return
'T'
elif
self
.
_square_topRight
.
contains
(
pointf
):
return
'TR'
elif
self
.
_square_leftMid
.
contains
(
pointf
):
return
'L'
elif
self
.
_rt_center
.
contains
(
pointf
):
return
'CENTER'
elif
self
.
_square_rightMid
.
contains
(
pointf
):
return
'R'
elif
self
.
_square_bottomLeft
.
contains
(
pointf
):
return
'BL'
elif
self
.
_square_bottomMid
.
contains
(
pointf
):
return
'B'
elif
self
.
_square_bottomRight
.
contains
(
pointf
):
return
'BR'
else
:
return
'ERROR'
def
adjustCenterAreaBy
(
self
,
pointf
):
'''根据开始调整截图区域大小时鼠标左键在哪个区(不可能是中央区域),判断调整大小的意图方向,判定新的开始、结束位置'''
startPointF
=
self
.
_rt_center
.
topLeft
()
endPointF
=
self
.
_rt_center
.
bottomRight
()
if
self
.
_mousePos
==
'TL'
:
startPointF
=
pointf
elif
self
.
_mousePos
==
'T'
:
startPointF
=
QPointF
(
startPointF
.
x
(),
pointf
.
y
())
elif
self
.
_mousePos
==
'TR'
:
startPointF
=
QPointF
(
startPointF
.
x
(),
pointf
.
y
())
endPointF
=
QPointF
(
pointf
.
x
(),
endPointF
.
y
())
elif
self
.
_mousePos
==
'L'
:
startPointF
=
QPointF
(
pointf
.
x
(),
startPointF
.
y
())
elif
self
.
_mousePos
==
'R'
:
endPointF
=
QPointF
(
pointf
.
x
(),
endPointF
.
y
())
elif
self
.
_mousePos
==
'BL'
:
startPointF
=
QPointF
(
pointf
.
x
(),
startPointF
.
y
())
endPointF
=
QPointF
(
endPointF
.
x
(),
pointf
.
y
())
elif
self
.
_mousePos
==
'B'
:
endPointF
=
QPointF
(
endPointF
.
x
(),
pointf
.
y
())
elif
self
.
_mousePos
==
'BR'
:
endPointF
=
pointf
else
:
# 'ERROR'
return
newRectF
=
self
.
normalizeRectF
(
startPointF
,
endPointF
)
self
.
setCenterArea
(
newRectF
.
topLeft
(),
newRectF
.
bottomRight
())
def
getMouseShapeBy
(
self
,
pointf
):
'''根据鼠标位置返回对应的鼠标样式'''
if
self
.
_rt_center
.
contains
(
pointf
):
if
self
.
god
.
isDrawRectangle
or
self
.
god
.
isDrawEllipse
:
return
QtCore
.
Qt
.
CursorShape
.
ArrowCursor
elif
self
.
god
.
isDrawGraffiti
:
return
QtCore
.
Qt
.
CursorShape
.
PointingHandCursor
# 超链接上的手势
elif
self
.
god
.
isDrawText
:
return
QtCore
.
Qt
.
CursorShape
.
IBeamCursor
# 工字
else
:
return
QtCore
.
Qt
.
CursorShape
.
SizeAllCursor
# 十字有箭头
# return QtCore.Qt.CursorShape.OpenHandCursor # 打开的手,表示可拖拽
elif
self
.
_square_topLeft
.
contains
(
pointf
)
or
self
.
_square_bottomRight
.
contains
(
pointf
):
return
QtCore
.
Qt
.
CursorShape
.
SizeFDiagCursor
# ↖↘
elif
self
.
_square_topMid
.
contains
(
pointf
)
or
self
.
_square_bottomMid
.
contains
(
pointf
):
return
QtCore
.
Qt
.
CursorShape
.
SizeVerCursor
# ↑↓
elif
self
.
_square_topRight
.
contains
(
pointf
)
or
self
.
_square_bottomLeft
.
contains
(
pointf
):
return
QtCore
.
Qt
.
CursorShape
.
SizeBDiagCursor
# ↙↗
elif
self
.
_square_leftMid
.
contains
(
pointf
)
or
self
.
_square_rightMid
.
contains
(
pointf
):
return
QtCore
.
Qt
.
CursorShape
.
SizeHorCursor
# ←→
else
:
return
QtCore
.
Qt
.
CursorShape
.
CrossCursor
# 十字无箭头
def
isMousePosInCenterRectF
(
self
,
pointf
):
return
self
.
_rt_center
.
contains
(
pointf
)
def
paintMagnifyingGlassPixmap
(
self
,
pos
,
glassSize
):
'''绘制放大镜内的图像(含纵横十字线)
pos:鼠标光标位置
glassSize:放大镜边框大小'''
pixmapRect
=
QRect
(
0
,
0
,
20
,
20
)
# 以鼠标光标为中心的正方形区域,最好是偶数
pixmapRect
.
moveCenter
(
pos
)
glassPixmap
=
self
.
physicalPixmap
(
pixmapRect
)
glassPixmap
.
setDevicePixelRatio
(
1.0
)
glassPixmap
=
glassPixmap
.
scaled
(
glassSize
,
glassSize
,
QtCore
.
Qt
.
AspectRatioMode
.
KeepAspectRatio
)
# 在放大后的QPixmap上画纵横十字线
self
.
_painter
.
begin
(
glassPixmap
)
halfWidth
=
glassPixmap
.
width
()
/
2
halfHeight
=
glassPixmap
.
height
()
/
2
self
.
_painter
.
setPen
(
self
.
god
.
pen_SolidLine_lightBlue
)
self
.
_painter
.
drawLine
(
QPointF
(
0
,
halfHeight
),
QPointF
(
glassPixmap
.
width
(),
halfHeight
))
self
.
_painter
.
drawLine
(
QPointF
(
halfWidth
,
0
),
QPointF
(
halfWidth
,
glassPixmap
.
height
()))
self
.
_painter
.
end
()
return
glassPixmap
def
paintEachEditAction
(
self
,
painter
,
textBorder
=
True
):
'''绘制所有已保存的编辑行为。编辑行为超出截图区域也无所谓,保存图像时只截取截图区域内
textBorder:是否绘制文本边框'''
for
action
in
self
.
getEditActions
():
if
action
[
0
]
==
'rectangle'
:
# (type, color, lineWidth, startPoint, endPoint)
self
.
paintRectangle
(
painter
,
action
[
1
],
action
[
2
],
action
[
3
],
action
[
4
])
elif
action
[
0
]
==
'ellipse'
:
# (type, color, lineWidth, startPoint, endPoint)
self
.
paintEllipse
(
painter
,
action
[
1
],
action
[
2
],
action
[
3
],
action
[
4
])
elif
action
[
0
]
==
'graffiti'
:
# (type, color, lineWidth, points)
self
.
paintGraffiti
(
painter
,
action
[
1
],
action
[
2
],
action
[
3
])
elif
action
[
0
]
==
'text'
:
# (type, color, font, rectf, txt)
self
.
paintTextInput
(
painter
,
action
[
1
],
action
[
2
],
action
[
3
],
action
[
4
],
textBorder
=
textBorder
)
def
paintRectangle
(
self
,
painter
,
color
,
lineWidth
,
startPoint
=
None
,
endPoint
=
None
):
if
not
startPoint
:
startPoint
=
self
.
_pt_startEdit
if
not
endPoint
:
endPoint
=
self
.
_pt_endEdit
qrectf
=
self
.
normalizeRectF
(
startPoint
,
endPoint
)
if
qrectf
.
isValid
():
pen
=
QPen
(
color
)
pen
.
setWidth
(
lineWidth
)
painter
.
setPen
(
pen
)
painter
.
setBrush
(
self
.
god
.
color_transparent
)
painter
.
drawRect
(
qrectf
)
def
paintEllipse
(
self
,
painter
,
color
,
lineWidth
,
startPoint
=
None
,
endPoint
=
None
):
if
not
startPoint
:
startPoint
=
self
.
_pt_startEdit
if
not
endPoint
:
endPoint
=
self
.
_pt_endEdit
qrectf
=
self
.
normalizeRectF
(
startPoint
,
endPoint
)
if
qrectf
.
isValid
():
pen
=
QPen
(
color
)
pen
.
setWidth
(
lineWidth
)
painter
.
setPen
(
pen
)
painter
.
setBrush
(
self
.
god
.
color_transparent
)
painter
.
drawEllipse
(
qrectf
)
def
paintGraffiti
(
self
,
painter
,
color
,
lineWidth
,
pointfs
=
None
):
if
not
pointfs
:
pointfs
=
self
.
getGraffitiPointFs
()
pen
=
QPen
(
color
)
pen
.
setWidth
(
lineWidth
)
painter
.
setPen
(
pen
)
total
=
len
(
pointfs
)
if
total
==
0
:
return
elif
total
==
1
:
painter
.
drawPoint
(
pointfs
[
0
])
else
:
previousPoint
=
pointfs
[
0
]
for
i
in
range
(
1
,
total
):
nextPoint
=
pointfs
[
i
]
painter
.
drawLine
(
previousPoint
,
nextPoint
)
previousPoint
=
nextPoint
def
paintTextInput
(
self
,
painter
,
color
,
font
,
rectf
,
txt
,
textBorder
=
True
):
painter
.
setPen
(
color
)
painter
.
setFont
(
font
)
painter
.
drawText
(
rectf
,
txt
,
self
.
_textOption
)
if
textBorder
:
painter
.
setPen
(
QtCore
.
Qt
.
PenStyle
.
DotLine
)
# 点线
painter
.
setBrush
(
self
.
god
.
color_transparent
)
painter
.
drawRect
(
rectf
)
def
getEditActions
(
self
):
return
self
.
_actions
.
copy
()
def
takeTextInputActionAt
(
self
,
pointf
):
'''根据鼠标位置查找已保存的文本输入结果,找到后取出'''
for
i
in
range
(
len
(
self
.
_actions
)):
action
=
self
.
_actions
[
i
]
if
action
[
0
]
==
'text'
and
action
[
3
].
contains
(
pointf
):
return
self
.
_actions
.
pop
(
i
)
return
None
def
undoEditAction
(
self
):
reply
=
False
if
self
.
_actions
:
reply
=
self
.
_actions
.
pop
()
if
not
self
.
_actions
:
# 所有编辑行为都被撤销后退出编辑模式
self
.
god
.
exitEditMode
()
else
:
self
.
god
.
exitEditMode
()
return
reply
def
clearEditActions
(
self
):
self
.
_actions
.
clear
()
def
setBeginEditPoint
(
self
,
pointf
):
'''在截图区域上绘制矩形、椭圆时鼠标左键按下的位置(topLeft)'''
self
.
_pt_startEdit
=
pointf
self
.
god
.
isDrawing
=
True
def
setEndEditPoint
(
self
,
pointf
):
'''在截图区域上绘制矩形、椭圆时鼠标左键松开的位置(bottomRight)'''
self
.
_pt_endEdit
=
pointf
def
saveRectangleAction
(
self
):
rectf
=
self
.
normalizeRectF
(
self
.
_pt_startEdit
,
self
.
_pt_endEdit
)
self
.
_actions
.
append
((
'rectangle'
,
self
.
god
.
toolbar
.
curColor
(),
self
.
god
.
toolbar
.
curLineWidth
(),
rectf
.
topLeft
(),
rectf
.
bottomRight
()))
self
.
_pt_startEdit
=
QPointF
()
self
.
_pt_endEdit
=
QPointF
()
self
.
god
.
isDrawing
=
False
def
saveEllipseleAction
(
self
):
rectf
=
self
.
normalizeRectF
(
self
.
_pt_startEdit
,
self
.
_pt_endEdit
)
self
.
_actions
.
append
((
'ellipse'
,
self
.
god
.
toolbar
.
curColor
(),
self
.
god
.
toolbar
.
curLineWidth
(),
rectf
.
topLeft
(),
rectf
.
bottomRight
()))
self
.
_pt_startEdit
=
QPointF
()
self
.
_pt_endEdit
=
QPointF
()
self
.
god
.
isDrawing
=
False
def
saveGraffitiPointF
(
self
,
pointf
,
first
=
False
):
self
.
_pointfs
.
append
(
pointf
)
if
first
:
self
.
god
.
isDrawing
=
True
def
getGraffitiPointFs
(
self
):
return
self
.
_pointfs
.
copy
()
def
saveGraffitiAction
(
self
):
if
self
.
_pointfs
:
self
.
_actions
.
append
((
'graffiti'
,
self
.
god
.
toolbar
.
curColor
(),
self
.
god
.
toolbar
.
curLineWidth
(),
self
.
_pointfs
.
copy
()))
self
.
_pointfs
.
clear
()
self
.
god
.
isDrawing
=
False
def
setBeginInputTextPoint
(
self
,
pointf
):
'''在截图区域上输入文字时鼠标左键按下的位置(topLeft)'''
self
.
god
.
isDrawing
=
True
self
.
god
.
textInputWg
.
beginNewInput
(
pointf
,
self
.
_pt_end
)
def
saveTextInputAction
(
self
):
txt
=
self
.
god
.
textInputWg
.
toPlainText
()
if
txt
:
rectf
=
self
.
god
.
textInputWg
.
_maxRect
# 取最大矩形的topLeft
rectf
.
setSize
(
QRectF
(
self
.
god
.
textInputWg
.
rect
()).
size
())
# 取实际矩形的宽高
self
.
_actions
.
append
((
'text'
,
self
.
god
.
toolbar
.
curColor
(),
self
.
god
.
toolbar
.
curFont
(),
rectf
,
txt
))
self
.
god
.
textInputWg
.
clear
()
self
.
god
.
textInputWg
.
hide
()
# 不管保存成功与否都取消编辑
self
.
god
.
isDrawing
=
False
def
saveNightAreaImg
(
self
):
'''将九宫格区域保存为本地图片,仅用于开发测试'''
screenPixmap
=
self
.
screenPhysicalPixmapCopy
()
self
.
_painter
.
begin
(
screenPixmap
)
self
.
_painter
.
setPen
(
self
.
pen_SolidLine_lightBlue
)
self
.
_painter
.
setFont
(
self
.
god
.
font_normal
)
self
.
_painter
.
drawRect
(
self
.
_rt_center
)
for
area
in
self
.
aroundAreaIn8Direction
():
self
.
_painter
.
drawRect
(
area
)
for
pointf
in
[
self
.
_rt_center
.
topLeft
(),
self
.
_rt_center
.
topRight
(),
self
.
_rt_center
.
bottomLeft
(),
self
.
_rt_center
.
bottomRight
(),
self
.
_pt_centerTopMid
,
self
.
_pt_centerBottomMid
,
self
.
_pt_centerLeftMid
,
self
.
_pt_centerRightMid
]:
self
.
_painter
.
drawText
(
pointf
+
QPointF
(
5
,
-
5
),
'(%s, %s)'
%
(
pointf
.
x
(),
pointf
.
y
()))
self
.
_painter
.
end
()
screenPixmap
.
save
(
'1.jpg'
,
quality
=
100
)
self
.
centerPhysicalPixmap
().
save
(
'2.jpg'
,
quality
=
100
)
class
ScreenShotWidget
(
QWidget
):
fileType_all
=
'所有文件 (*);;Excel文件 (*.xls *.xlsx);;图片文件 (*.jpg *.jpeg *.gif *.png *.bmp)'
fileType_img
=
'图片文件 (*.jpg *.jpeg *.gif *.png *.bmp)'
dir_lastAccess
=
os
.
getcwd
()
# 最后访问目录
def
__init__
(
self
):
super
().
__init__
()
self
.
setMouseTracking
(
True
)
self
.
setWindowFlags
(
QtCore
.
Qt
.
WindowType
.
FramelessWindowHint
|
QtCore
.
Qt
.
WindowType
.
WindowStaysOnTopHint
)
self
.
initPainterTool
()
self
.
initFunctionalFlag
()
self
.
screenArea
=
ScreenArea
(
self
)
self
.
toolbar
=
ScreenShotToolBar
(
self
)
self
.
textInputWg
=
TextInputWidget
(
self
)
self
.
captureImage
=
None
# 设置 screenPixmap 为窗口背景
# palette = QtGui.QPalette()
# palette.setBrush(QtGui.QPalette.ColorRole.Window, QtGui.QBrush(self.screenArea.screenPhysicalPixmapCopy()))
# self.setPalette(palette)
def
rejectSlot
(
self
):
self
.
captureImage
=
None
self
.
close
()
def
acceptSlot
(
self
):
self
.
captureImage
=
self
.
screenArea
.
centerPhysicalPixmap
().
toImage
()
self
.
close
()
def
start
(
self
):
self
.
screenArea
.
captureScreen
()
self
.
setGeometry
(
self
.
screenArea
.
screenPhysicalRectF
().
toRect
())
self
.
clearScreenShotArea
()
self
.
showFullScreen
()
def
initPainterTool
(
self
):
self
.
painter
=
QPainter
()
self
.
color_transparent
=
QtCore
.
Qt
.
GlobalColor
.
transparent
self
.
color_black
=
QColor
(
0
,
0
,
0
,
64
)
# 黑色背景
self
.
color_lightBlue
=
QColor
(
30
,
120
,
255
)
# 浅蓝色。深蓝色QtCore.Qt.GlobalColor.blue
self
.
font_normal
=
QtGui
.
QFont
(
'Times New Roman'
,
11
,
QtGui
.
QFont
.
Weight
.
Normal
)
self
.
font_textInput
=
QtGui
.
QFont
(
'微软雅黑'
,
16
,
QtGui
.
QFont
.
Weight
.
Normal
)
# 工具条文字工具默认字体
self
.
pen_transparent
=
QPen
(
QtCore
.
Qt
.
PenStyle
.
NoPen
)
# 没有笔迹,画不出线条
self
.
pen_white
=
QPen
(
QtCore
.
Qt
.
GlobalColor
.
white
)
self
.
pen_SolidLine_lightBlue
=
QPen
(
self
.
color_lightBlue
)
# 实线,浅蓝色
self
.
pen_SolidLine_lightBlue
.
setStyle
(
QtCore
.
Qt
.
PenStyle
.
DashLine
)
# 实线SolidLine,虚线DashLine,点线DotLine
self
.
pen_SolidLine_lightBlue
.
setWidthF
(
0
)
# 0表示线宽为1
self
.
pen_DashLine_lightBlue
=
QPen
(
self
.
color_lightBlue
)
# 虚线,浅蓝色
self
.
pen_DashLine_lightBlue
.
setStyle
(
QtCore
.
Qt
.
PenStyle
.
DashLine
)
def
initFunctionalFlag
(
self
):
self
.
hasScreenShot
=
False
# 是否已通过拖动鼠标左键划定截图区域
self
.
isCapturing
=
False
# 正在拖动鼠标左键选定截图区域时
self
.
isMoving
=
False
# 在截图区域内拖动时
self
.
isAdjusting
=
False
# 在截图区域的边框按住鼠标左键调整大小时
self
.
isDrawing
=
False
# 是否已在截图区域内开始绘制
self
.
isDrawRectangle
=
False
# 正在截图区域内画矩形
self
.
isDrawEllipse
=
False
# 正在截图区域内画椭圆
self
.
isDrawGraffiti
=
False
# 正在截图区域内进行涂鸦
self
.
isDrawText
=
False
# 正在截图区域内画文字
self
.
setCursor
(
QtCore
.
Qt
.
CursorShape
.
CrossCursor
)
# 设置鼠标样式 十字
def
paintEvent
(
self
,
event
):
centerRectF
=
self
.
screenArea
.
centerLogicalRectF
()
screenSizeF
=
self
.
screenArea
.
screenLogicalSizeF
()
canvasPixmap
=
self
.
screenArea
.
screenPhysicalPixmapCopy
()
# canvasPixmap = QPixmap(screenSizeF.toSize())
# canvasPixmap.fill(self.color_transparent)
# 在屏幕截图的副本上绘制已选定的截图区域
self
.
painter
.
begin
(
canvasPixmap
)
if
self
.
hasScreenShot
:
self
.
paintCenterArea
(
centerRectF
)
# 绘制中央截图区域
self
.
paintMaskLayer
(
screenSizeF
,
fullScreen
=
False
)
# 绘制截图区域的周边区域遮罩层
else
:
self
.
paintMaskLayer
(
screenSizeF
)
self
.
paintMagnifyingGlass
(
screenSizeF
)
# 在鼠标光标右下角显示放大镜
self
.
paintToolbar
(
centerRectF
,
screenSizeF
)
# 在截图区域右下角显示工具条
self
.
paintEditActions
()
# 在截图区域绘制编辑行为结果
self
.
painter
.
end
()
# 把画好的绘制结果显示到窗口上
self
.
painter
.
begin
(
self
)
self
.
painter
.
drawPixmap
(
0
,
0
,
canvasPixmap
)
# 从坐标(0, 0)开始绘制
self
.
painter
.
end
()
def
paintCenterArea
(
self
,
centerRectF
):
'''绘制已选定的截图区域'''
self
.
painter
.
setRenderHint
(
QPainter
.
RenderHint
.
Antialiasing
,
True
)
# 反走样
# 1.绘制矩形线框
self
.
painter
.
setPen
(
self
.
pen_DashLine_lightBlue
)
self
.
painter
.
drawRect
(
centerRectF
)
# 2.绘制矩形线框4个端点和4条边框的中间点
if
centerRectF
.
width
()
>=
100
and
centerRectF
.
height
()
>=
100
:
points
=
[
# 点坐标
centerRectF
.
topLeft
(),
centerRectF
.
topRight
(),
centerRectF
.
bottomLeft
(),
centerRectF
.
bottomRight
(),
self
.
screenArea
.
centerLeftMid
(),
self
.
screenArea
.
centerRightMid
(),
self
.
screenArea
.
centerTopMid
(),
self
.
screenArea
.
centerBottomMid
()
]
blueDotRadius
=
QPointF
(
2
,
2
)
# 椭圆蓝点
self
.
painter
.
setBrush
(
self
.
color_lightBlue
)
for
point
in
points
:
self
.
painter
.
drawEllipse
(
QRectF
(
point
-
blueDotRadius
,
point
+
blueDotRadius
))
# 3.在截图区域左上角显示截图区域宽高
if
centerRectF
.
topLeft
().
y
()
>
20
:
labelPos
=
centerRectF
.
topLeft
()
+
QPointF
(
5
,
-
5
)
else
:
# 拖拽截图区域到贴近屏幕上边缘时“宽x高”移动到截图区域左上角的下侧
labelPos
=
centerRectF
.
topLeft
()
+
QPointF
(
5
,
15
)
centerPhysicalRect
=
self
.
screenArea
.
centerPhysicalRectF
().
toRect
()
self
.
painter
.
setPen
(
self
.
pen_white
)
self
.
painter
.
setFont
(
self
.
font_normal
)
self
.
painter
.
drawText
(
labelPos
,
'%s x %s'
%
(
centerPhysicalRect
.
width
(),
centerPhysicalRect
.
height
()))
# 4.在屏幕左上角预览截图结果
# self.painter.drawPixmap(0, 0, self.screenArea.centerPhysicalPixmap()) # 从坐标(0, 0)开始绘制
def
paintMaskLayer
(
self
,
screenSizeF
,
fullScreen
=
True
):
if
fullScreen
:
# 全屏遮罩层
maskPixmap
=
QPixmap
(
screenSizeF
.
toSize
())
maskPixmap
.
fill
(
self
.
color_black
)
self
.
painter
.
drawPixmap
(
0
,
0
,
maskPixmap
)
else
:
# 绘制截图区域的周边区域遮罩层,以凸显截图区域
# 方法一:截图区域以外的8个方向区域
# for area in self.screenArea.aroundAreaIn8Direction():
# area = area.normalized()
# maskPixmap = QPixmap(area.size().toSize()) # 由于float转int的精度问题,可能会存在黑线条缝隙
# maskPixmap.fill(self.color_black)
# self.painter.drawPixmap(area.topLeft(), maskPixmap)
# 方法二:截图区域以外的上下左右区域(有交集,交集部分颜色加深,有明显的纵横效果)
# for area in self.screenArea.aroundAreaIn4Direction():
# maskPixmap = QPixmap(area.size().toSize())
# maskPixmap.fill(self.color_black)
# self.painter.drawPixmap(area.topLeft(), maskPixmap)
# 方法三:截图区域以外的上下左右区域(无交集)
for
area
in
self
.
screenArea
.
aroundAreaWithoutIntersection
():
maskPixmap
=
QPixmap
(
area
.
size
().
toSize
())
maskPixmap
.
fill
(
self
.
color_black
)
self
.
painter
.
drawPixmap
(
area
.
topLeft
(),
maskPixmap
)
def
paintMagnifyingGlass
(
self
,
screenSizeF
,
glassSize
=
150
,
offset
=
30
,
labelHeight
=
30
):
'''未划定截图区域模式时、正在划定截取区域时、调整截取区域大小时在鼠标光标右下角显示放大镜
glassSize:放大镜正方形边长
offset:放大镜任意一个端点距离鼠标光标位置的最近距离
labelHeight:pos和rgb两行文字的高度'''
if
self
.
hasScreenShot
and
(
not
self
.
isCapturing
)
and
(
not
self
.
isAdjusting
):
return
pos
=
QtGui
.
QCursor
.
pos
()
glassPixmap
=
self
.
screenArea
.
paintMagnifyingGlassPixmap
(
pos
,
glassSize
)
# 画好纵横十字线后的放大镜内QPixmap
# 限制放大镜显示不超出屏幕外
glassRect
=
glassPixmap
.
rect
()
if
(
pos
.
x
()
+
glassSize
+
offset
)
<
screenSizeF
.
width
():
if
(
pos
.
y
()
+
offset
+
glassSize
+
labelHeight
)
<
screenSizeF
.
height
():
glassRect
.
moveTo
(
pos
+
QPoint
(
offset
,
offset
))
else
:
glassRect
.
moveBottomLeft
(
pos
+
QPoint
(
offset
,
-
offset
))
else
:
if
(
pos
.
y
()
+
offset
+
glassSize
+
labelHeight
)
<
screenSizeF
.
height
():
glassRect
.
moveTopRight
(
pos
+
QPoint
(
-
offset
,
offset
))
else
:
glassRect
.
moveBottomRight
(
pos
+
QPoint
(
-
offset
,
-
offset
))
self
.
painter
.
drawPixmap
(
glassRect
.
topLeft
(),
glassPixmap
)
# 显示pos:(x, y)、rgb:(255,255,255)
qrgb
=
QtGui
.
QRgba64
.
fromArgb32
(
glassPixmap
.
toImage
().
pixel
(
glassPixmap
.
rect
().
center
()))
labelRectF
=
QRectF
(
glassRect
.
bottomLeft
().
x
(),
glassRect
.
bottomLeft
().
y
(),
glassSize
,
labelHeight
)
self
.
painter
.
setPen
(
self
.
pen_transparent
)
self
.
painter
.
setBrush
(
self
.
color_black
)
# 黑底
self
.
painter
.
drawRect
(
labelRectF
)
self
.
painter
.
setPen
(
self
.
pen_white
)
self
.
painter
.
setFont
(
self
.
font_normal
)
self
.
painter
.
drawText
(
labelRectF
,
QtCore
.
Qt
.
AlignmentFlag
.
AlignLeft
|
QtCore
.
Qt
.
AlignmentFlag
.
AlignVCenter
,
'pos:(%s, %s)
\n
rgb:(%s, %s, %s)'
%
(
pos
.
x
(),
pos
.
y
(),
qrgb
.
red8
(),
qrgb
.
green8
(),
qrgb
.
blue8
()))
def
paintToolbar
(
self
,
centerRectF
,
screenSizeF
):
'''在截图区域右下角显示工具条'''
if
self
.
hasScreenShot
:
if
self
.
isCapturing
or
self
.
isAdjusting
:
self
.
toolbar
.
hide
()
# 正在划定截取区域时、调整截图区域大小时不显示工具条
else
:
self
.
toolbar
.
adjustSize
()
toolbarRectF
=
QRectF
(
self
.
toolbar
.
rect
())
# 工具条位置优先顺序:右下角下侧,右上角上侧,右下角上侧
if
(
screenSizeF
.
height
()
-
centerRectF
.
bottomRight
().
y
())
>
toolbarRectF
.
height
():
toolbarRectF
.
moveTopRight
(
centerRectF
.
bottomRight
()
+
QPointF
(
-
5
,
5
))
elif
centerRectF
.
topRight
().
y
()
>
toolbarRectF
.
height
():
toolbarRectF
.
moveBottomRight
(
centerRectF
.
topRight
()
+
QPointF
(
-
5
,
-
5
))
else
:
toolbarRectF
.
moveBottomRight
(
centerRectF
.
bottomRight
()
+
QPointF
(
-
5
,
-
5
))
# 限制工具条的x坐标不为负数,不能移出屏幕外
if
toolbarRectF
.
x
()
<
0
:
pos
=
toolbarRectF
.
topLeft
()
pos
.
setX
(
centerRectF
.
x
()
+
5
)
toolbarRectF
.
moveTo
(
pos
)
self
.
toolbar
.
move
(
toolbarRectF
.
topLeft
().
toPoint
())
self
.
toolbar
.
show
()
else
:
self
.
toolbar
.
hide
()
def
paintEditActions
(
self
):
'''在截图区域绘制编辑行为结果。编辑行为超出截图区域也无所谓,保存图像时只截取截图区域内'''
# 1.绘制正在拖拽编辑中的矩形、椭圆、涂鸦
if
self
.
isDrawRectangle
:
self
.
screenArea
.
paintRectangle
(
self
.
painter
,
self
.
toolbar
.
curColor
(),
self
.
toolbar
.
curLineWidth
())
elif
self
.
isDrawEllipse
:
self
.
screenArea
.
paintEllipse
(
self
.
painter
,
self
.
toolbar
.
curColor
(),
self
.
toolbar
.
curLineWidth
())
elif
self
.
isDrawGraffiti
:
self
.
screenArea
.
paintGraffiti
(
self
.
painter
,
self
.
toolbar
.
curColor
(),
self
.
toolbar
.
curLineWidth
())
# 2.绘制所有已保存的编辑行为
self
.
screenArea
.
paintEachEditAction
(
self
.
painter
)
def
clearEditFlags
(
self
):
self
.
isDrawing
=
False
self
.
isDrawRectangle
=
False
self
.
isDrawEllipse
=
False
self
.
isDrawGraffiti
=
False
self
.
isDrawText
=
False
def
exitEditMode
(
self
):
'''退出编辑模式'''
self
.
clearEditFlags
()
# self.toolbar.onActionTriggered(None) # 清空工具条工具按钮选中状态
self
.
textInputWg
.
hide
()
def
clearScreenShotArea
(
self
):
'''清空已划定的截取区域'''
self
.
screenArea
.
clearEditActions
()
# 清除已保存的编辑行为
self
.
exitEditMode
()
self
.
hasScreenShot
=
False
self
.
isCapturing
=
False
pos
=
QPointF
()
self
.
screenArea
.
setCenterArea
(
pos
,
pos
)
self
.
update
()
self
.
setCursor
(
QtCore
.
Qt
.
CursorShape
.
CrossCursor
)
# 设置鼠标样式 十字
def
mousePressEvent
(
self
,
event
):
if
event
.
button
()
==
QtCore
.
Qt
.
MouseButton
.
LeftButton
:
pos
=
event
.
pos
()
if
self
.
hasScreenShot
:
if
self
.
isDrawRectangle
or
self
.
isDrawEllipse
:
self
.
screenArea
.
setBeginEditPoint
(
pos
)
elif
self
.
isDrawGraffiti
:
# 保存涂鸦经过的每一个点
self
.
screenArea
.
saveGraffitiPointF
(
pos
,
first
=
True
)
elif
self
.
isDrawText
:
if
self
.
isDrawing
:
if
QRectF
(
self
.
textInputWg
.
rect
()).
contains
(
pos
):
pass
# 在输入框内调整光标位置,忽略
else
:
# 鼠标点到输入框之外,完成编辑
self
.
screenArea
.
saveTextInputAction
()
else
:
# 未开始编辑时(暂不支持文本拖拽)
action
=
self
.
screenArea
.
takeTextInputActionAt
(
pos
)
if
action
:
# 鼠标点到输入框之内,修改旧的文本输入
self
.
textInputWg
.
loadTextInputBy
(
action
)
else
:
# 鼠标点到输入框之外,开始新的文本输入
self
.
screenArea
.
setBeginInputTextPoint
(
pos
)
elif
self
.
screenArea
.
isMousePosInCenterRectF
(
pos
):
self
.
isMoving
=
True
# 进入拖拽移动模式
self
.
screenArea
.
setBeginDragPoint
(
pos
)
else
:
self
.
isAdjusting
=
True
# 进入调整大小模式
self
.
screenArea
.
setBeginAdjustPoint
(
pos
)
else
:
self
.
screenArea
.
setCenterArea
(
pos
,
pos
)
self
.
isCapturing
=
True
# 进入划定截图区域模式
if
event
.
button
()
==
QtCore
.
Qt
.
MouseButton
.
RightButton
:
if
self
.
hasScreenShot
or
self
.
isCapturing
:
# 清空已划定的的截图区域
self
.
clearScreenShotArea
()
else
:
self
.
close
()
def
mouseReleaseEvent
(
self
,
event
):
if
event
.
button
()
==
QtCore
.
Qt
.
MouseButton
.
LeftButton
:
if
self
.
isDrawRectangle
:
self
.
screenArea
.
saveRectangleAction
()
elif
self
.
isDrawEllipse
:
self
.
screenArea
.
saveEllipseleAction
()
elif
self
.
isDrawGraffiti
:
self
.
screenArea
.
saveGraffitiAction
()
self
.
isCapturing
=
False
self
.
isMoving
=
False
self
.
isAdjusting
=
False
self
.
toolbar
.
show
()
def
mouseMoveEvent
(
self
,
event
):
pos
=
event
.
pos
()
if
self
.
isDrawing
:
if
self
.
isDrawRectangle
or
self
.
isDrawEllipse
:
self
.
screenArea
.
setEndEditPoint
(
pos
)
elif
self
.
isDrawGraffiti
:
self
.
screenArea
.
saveGraffitiPointF
(
pos
)
elif
self
.
isCapturing
:
self
.
hasScreenShot
=
True
self
.
screenArea
.
setEndPoint
(
pos
,
remake
=
True
)
elif
self
.
isMoving
:
self
.
screenArea
.
moveCenterAreaTo
(
pos
)
elif
self
.
isAdjusting
:
self
.
screenArea
.
adjustCenterAreaBy
(
pos
)
self
.
update
()
if
self
.
hasScreenShot
:
self
.
setCursor
(
self
.
screenArea
.
getMouseShapeBy
(
pos
))
else
:
self
.
setCursor
(
QtCore
.
Qt
.
CursorShape
.
CrossCursor
)
# 设置鼠标样式 十字
def
mouseDoubleClickEvent
(
self
,
event
):
if
event
.
button
()
==
QtCore
.
Qt
.
MouseButton
.
LeftButton
:
if
self
.
screenArea
.
isMousePosInCenterRectF
(
event
.
pos
()):
self
.
save2Clipboard
()
self
.
close
()
def
keyPressEvent
(
self
,
QKeyEvent
):
if
QKeyEvent
.
key
()
==
QtCore
.
Qt
.
Key
.
Key_Escape
:
self
.
close
()
if
QKeyEvent
.
key
()
in
(
QtCore
.
Qt
.
Key
.
Key_Return
,
QtCore
.
Qt
.
Key
.
Key_Enter
):
# 大键盘、小键盘回车
self
.
save2Clipboard
()
self
.
close
()
def
save2Clipboard
(
self
):
'''将截图区域复制到剪贴板'''
if
self
.
hasScreenShot
:
mimData
=
QtCore
.
QMimeData
()
mimData
.
setImageData
(
self
.
screenArea
.
centerPhysicalPixmap
().
toImage
())
QApplication
.
clipboard
().
setMimeData
(
mimData
)
# self.screenArea.saveNightAreaImg()
self
.
close
()
def
save2Local
(
self
):
fileType
=
self
.
fileType_img
filePath
,
fileFormat
=
self
.
sys_selectSaveFilePath
(
self
,
fileType
=
fileType
)
if
filePath
:
self
.
screenArea
.
centerPhysicalPixmap
().
save
(
filePath
,
quality
=
100
)
self
.
close
()
def
sys_getCurTime
(
self
,
fmt
=
'%Y-%m-%d %H:%M:%S'
):
'''获取字符串格式的当前时间'''
# return QtCore.QDateTime.currentDateTime().toString('yyyy-MM-dd hh:mm:ss')
return
datetime
.
now
().
strftime
(
fmt
)
def
sys_selectSaveFilePath
(
self
,
widget
,
title
=
'选择文件保存路径'
,
saveFileDir
=
None
,
saveFileName
=
''
,
defaultFileFmt
=
'%Y%m%d%H%M%S'
,
fileType
=
None
):
'''选择文件保存路径
title:选择窗口标题
saveFileDir:指定保存目录
saveFileName:默认保存文件名
defaultFileFmt:不指定saveFileName时,自动以此格式的时间字符串命名文件
fileType:可以选择的文件类型
return:(所选的文件保存路径, 文件的类型)
'''
options
=
QFileDialog
.
Option
.
ReadOnly
if
saveFileName
==
''
:
saveFileName
=
self
.
sys_getCurTime
(
defaultFileFmt
)
if
not
saveFileDir
:
saveFileDir
=
self
.
dir_lastAccess
saveFilePath
=
os
.
path
.
join
(
saveFileDir
,
saveFileName
)
if
not
fileType
:
fileType
=
self
.
fileType_all
filePath
,
fileFormat
=
QFileDialog
.
getSaveFileName
(
widget
,
title
,
saveFilePath
,
fileType
,
options
=
options
)
if
filePath
:
self
.
dir_lastAccess
=
os
.
path
.
dirname
(
filePath
)
return
(
filePath
,
fileFormat
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录