1 Star 0 Fork 1

OpenCG/smart_qtwidgets

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
thumbnail_grab_widget.py 8.44 KB
一键复制 编辑 原始数据 按行查看 历史
sheen 提交于 2021-08-04 14:53 . 更新
#!/usr/bin/env python
# -*- coding: utf8 -*-
import os
import sys
import tempfile
from qtpy import QtWidgets, QtCore, QtGui
from .ui.thumbnail_grab_widget import Ui_ThumbnailWidget
from . import screen_grab
class ThumbnailGrabWidget(QtWidgets.QWidget):
"""
Thumbnail widget that provides screen capture functionality
"""
thumbnail_changed = QtCore.Signal()
def __init__(self, parent=None):
"""
Construction
"""
QtWidgets.QWidget.__init__(self, parent)
self._ui = Ui_ThumbnailWidget()
self._ui.setupUi(self)
# create layout to control buttons frame
layout = QtWidgets.QHBoxLayout()
layout.addWidget(self._ui.buttons_frame)
layout.setContentsMargins(0,0,0,0)
layout.setSpacing(0)
self.setLayout(layout)
# connect to buttons:
self._ui.camera_btn.clicked.connect(self._on_camera_clicked)
self._btns_transition_anim = None
self._update_ui()
# @property
def _get_thumbnail(self):
pm = self._ui.thumbnail.pixmap()
return pm if pm and not pm.isNull() else None
# @thumbnail.setter
def _set_thumbnail(self, value):
self._ui.thumbnail.setPixmap(value if value else QtGui.QPixmap())
self._update_ui()
self.thumbnail_changed.emit()
thumbnail = property(_get_thumbnail, _set_thumbnail)
def enable_screen_capture(self, enable):
self._ui.camera_btn.setVisible(enable)
def resizeEvent(self, event):
self._update_ui()
def enterEvent(self, event):
"""
when the cursor enters the control, show the buttons
"""
if self.thumbnail and self._are_any_btns_enabled():
self._ui.buttons_frame.show()
if hasattr(QtCore, "QAbstractAnimation"):
self._run_btns_transition_anim(QtCore.QAbstractAnimation.Forward)
else:
# Q*Animation classes aren't available so just
# make sure the button is visible:
self.btn_visibility = 1.0
def leaveEvent(self, event):
"""
when the cursor leaves the control, hide the buttons
"""
if self.thumbnail and self._are_any_btns_enabled():
if hasattr(QtCore, "QAbstractAnimation"):
self._run_btns_transition_anim(QtCore.QAbstractAnimation.Backward)
else:
# Q*Animation classes aren't available so just
# make sure the button is hidden:
self._ui.buttons_frame.hide()
self.btn_visibility = 0.0
def _are_any_btns_enabled(self):
"""
Return if any of the buttons are enabled
"""
return not (self._ui.camera_btn.isHidden())
"""
button visibility property used by QPropertyAnimation
"""
def get_btn_visibility(self):
return self._btns_visibility
def set_btn_visibility(self, value):
self._btns_visibility = value
self._ui.buttons_frame.setStyleSheet("#buttons_frame {border-radius: 2px; background-color: rgba(32, 32, 32, %d);}" % (64 * value))
btn_visibility = QtCore.Property(float, get_btn_visibility, set_btn_visibility)
def _run_btns_transition_anim(self, direction):
"""
Run the transition animation for the buttons
"""
if not self._btns_transition_anim:
# set up anim:
if sys.version.startswith('3.'):
self._btns_transition_anim = QtCore.QPropertyAnimation(self, "btn_visibility".encode('utf-8'))
else:
self._btns_transition_anim = QtCore.QPropertyAnimation(self, "btn_visibility")
self._btns_transition_anim.setDuration(150)
self._btns_transition_anim.setStartValue(0.0)
self._btns_transition_anim.setEndValue(1.0)
self._btns_transition_anim.finished.connect(self._on_btns_transition_anim_finished)
if self._btns_transition_anim.state() == QtCore.QAbstractAnimation.Running:
if self._btns_transition_anim.direction() != direction:
self._btns_transition_anim.pause()
self._btns_transition_anim.setDirection(direction)
self._btns_transition_anim.resume()
else:
pass # just let animation continue!
else:
self._btns_transition_anim.setDirection(direction)
self._btns_transition_anim.start()
def _on_btns_transition_anim_finished(self):
if self._btns_transition_anim.direction() == QtCore.QAbstractAnimation.Backward:
self._ui.buttons_frame.hide()
def _on_camera_clicked(self):
pm = self._on_screenshot()
if pm:
self.thumbnail = pm
def _update_ui(self):
# maximum size of thumbnail is widget geom:
thumbnail_geom = self.geometry()
thumbnail_geom.moveTo(0,0)
scale_contents = False
pm = self.thumbnail
if pm:
# work out size thumbnail should be to maximize size
# whilst retaining aspect ratio
pm_sz = pm.size()
h_scale = float(thumbnail_geom.height()-4)/float(pm_sz.height())
w_scale = float(thumbnail_geom.width()-4)/float(pm_sz.width())
scale = min(1.0, h_scale, w_scale)
scale_contents = (scale < 1.0)
new_height = min(int(pm_sz.height() * scale), thumbnail_geom.height())
new_width = min(int(pm_sz.width() * scale), thumbnail_geom.width())
new_geom = QtCore.QRect(thumbnail_geom)
new_geom.moveLeft(((thumbnail_geom.width()-4)/2 - new_width/2)+2)
new_geom.moveTop(((thumbnail_geom.height()-4)/2 - new_height/2)+2)
new_geom.setWidth(new_width)
new_geom.setHeight(new_height)
thumbnail_geom = new_geom
self._ui.thumbnail.setScaledContents(scale_contents)
self._ui.thumbnail.setGeometry(thumbnail_geom)
# now update buttons based on current thumbnail:
if not self._btns_transition_anim or self._btns_transition_anim.state() == QtCore.QAbstractAnimation.Stopped:
if self.thumbnail or not self._are_any_btns_enabled():
self._ui.buttons_frame.hide()
self._btns_visibility = 0.0
else:
self._ui.buttons_frame.show()
self._btns_visibility = 1.0
def _safe_get_dialog(self):
"""
Get the widgets dialog parent.
just call self.window() but this is unstable in Nuke
Previously this would
causing a crash on exit - suspect that it's caching
something internally which then doesn't get cleaned
up properly...
"""
current_widget = self
while current_widget:
if isinstance(current_widget, QtWidgets.QDialog):
return current_widget
current_widget = current_widget.parentWidget()
return None
def _on_screenshot(self):
"""
Perform the actual screenshot
"""
# hide the containing window - we can't actuall hide
# the window as this will break modality! Instead
# we have to move the window off the screen:
win = self._safe_get_dialog()
win_geom = None
if win:
win_geom = win.geometry()
win.setGeometry(1000000, 1000000, win_geom.width(), win_geom.height())
# make sure this event is processed:
QtCore.QCoreApplication.processEvents()
QtCore.QCoreApplication.sendPostedEvents(None, 0)
QtCore.QCoreApplication.flush()
try:
# get temporary file to use:
# to be cross-platform and python 2.5 compliant, we can't use
# tempfile.NamedTemporaryFile with delete=False. Instead, we
# use tempfile.mkstemp which does practically the same thing!
tf, path = tempfile.mkstemp(suffix=".png", prefix="tanktmp")
if tf:
os.close(tf)
pm = screen_grab.screen_capture()
finally:
# restore the window:
if win:
win.setGeometry(win_geom)
QtCore.QCoreApplication.processEvents()
return pm
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/tdercg/smart_qtwidgets.git
git@gitee.com:tdercg/smart_qtwidgets.git
tdercg
smart_qtwidgets
smart_qtwidgets
master

搜索帮助