You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
9.6 KiB
Python

2 years ago
import webbrowser
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QPropertyAnimation, QPoint, QTimer, pyqtSignal
from PyQt5.QtWidgets import QWidget, QPushButton
class Ui_NotifyForm(object):
def setupUi(self, NotifyForm):
NotifyForm.setObjectName("NotifyForm")
NotifyForm.resize(300, 200)
NotifyForm.setStyleSheet("QWidget#widgetTitle {\n"
" background-color: rgb(76, 169, 106);\n"
"}\n"
"QWidget#widgetBottom {\n"
" border-top-style: solid;\n"
" border-top-width: 2px;\n"
" border-top-color: rgb(185, 218, 201);\n"
"}\n"
"QLabel#labelTitle {\n"
" color: rgb(255, 255, 255);\n"
"}\n"
"QLabel#labelContent {\n"
" padding: 5px;\n"
"}\n"
"QPushButton {\n"
" border: none;\n"
" background: transparent;\n"
"}\n"
"QPushButton#buttonClose {\n"
" font-family: \"webdings\";\n"
" color: rgb(255, 255, 255);\n"
"}\n"
"QPushButton#buttonClose:hover {\n"
" background-color: rgb(212, 64, 39);\n"
"}\n"
"QPushButton#buttonView {\n"
" color: rgb(255, 255, 255);\n"
" border-radius: 5px;\n"
" border: solid 1px rgb(76, 169, 106);\n"
" background-color: rgb(76, 169, 106);\n"
"}\n"
"QPushButton#buttonView:hover {\n"
" color: rgb(0, 0, 0);\n"
"}")
self.verticalLayout = QtWidgets.QVBoxLayout(NotifyForm)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(6)
self.verticalLayout.setObjectName("verticalLayout")
self.widgetTitle = QtWidgets.QWidget(NotifyForm)
self.widgetTitle.setMinimumSize(QtCore.QSize(0, 26))
self.widgetTitle.setObjectName("widgetTitle")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widgetTitle)
self.horizontalLayout_3.setContentsMargins(10, 0, 0, 0)
self.horizontalLayout_3.setSpacing(0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.labelTitle = QtWidgets.QLabel(self.widgetTitle)
self.labelTitle.setText("")
self.labelTitle.setObjectName("labelTitle")
self.horizontalLayout_3.addWidget(self.labelTitle)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem)
self.buttonClose = QtWidgets.QPushButton(self.widgetTitle)
self.buttonClose.setMinimumSize(QtCore.QSize(26, 26))
self.buttonClose.setMaximumSize(QtCore.QSize(26, 26))
self.buttonClose.setObjectName("buttonClose")
self.horizontalLayout_3.addWidget(self.buttonClose)
self.verticalLayout.addWidget(self.widgetTitle)
self.labelContent = QtWidgets.QLabel(NotifyForm)
self.labelContent.setText("")
self.labelContent.setWordWrap(True)
self.labelContent.setObjectName("labelContent")
self.verticalLayout.addWidget(self.labelContent)
self.widgetBottom = QtWidgets.QWidget(NotifyForm)
self.widgetBottom.setObjectName("widgetBottom")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.widgetBottom)
self.horizontalLayout.setContentsMargins(0, 5, 5, 5)
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem1 = QtWidgets.QSpacerItem(170, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
self.buttonView = QtWidgets.QPushButton(self.widgetBottom)
self.buttonView.setMinimumSize(QtCore.QSize(75, 25))
self.buttonView.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.buttonView.setObjectName("buttonView")
self.horizontalLayout.addWidget(self.buttonView)
self.verticalLayout.addWidget(self.widgetBottom)
self.verticalLayout.setStretch(1, 1)
self.retranslateUi(NotifyForm)
QtCore.QMetaObject.connectSlotsByName(NotifyForm)
def retranslateUi(self, NotifyForm):
_translate = QtCore.QCoreApplication.translate
NotifyForm.setWindowTitle(_translate("NotifyForm", "消息提示"))
self.buttonClose.setText(_translate("NotifyForm", "r"))
self.buttonView.setText(_translate("NotifyForm", "查 看"))
class WindowNotify(QWidget, Ui_NotifyForm):
SignalClosed = pyqtSignal() # 弹窗关闭信号
def __init__(self, title="", content="", timeout=5000, *args, **kwargs):
super(WindowNotify, self).__init__(*args, **kwargs)
self.setupUi(self)
self.setTitle(title).setContent(content)
self._timeout = timeout
self._init()
def setTitle(self, title):
if title:
self.labelTitle.setText(title)
return self
def title(self):
return self.labelTitle.text()
def setContent(self, content):
if content:
self.labelContent.setText(content)
return self
def content(self):
return self.labelContent.text()
def setTimeout(self, timeout):
if isinstance(timeout, int):
self._timeout = timeout
return self
def timeout(self):
return self._timeout
def onView(self):
print("onView")
webbrowser.open_new_tab("http://alyl.vip")
def onClose(self):
#点击关闭按钮时
print("onClose")
self.isShow = False
QTimer.singleShot(100, self.closeAnimation)#启动弹回动画
def _init(self):
# 隐藏任务栏|去掉边框|顶层显示
self.setWindowFlags(Qt.Tool | Qt.X11BypassWindowManagerHint |
Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
# 关闭按钮事件
self.buttonClose.clicked.connect(self.onClose)
# 点击查看按钮
self.buttonView.clicked.connect(self.onView)
# 是否在显示标志
self.isShow = True
# 超时
self._timeouted = False
# 桌面
self._desktop = QApplication.instance().desktop()
# 窗口初始开始位置
self._startPos = QPoint(
self._desktop.screenGeometry().width() - self.width() - 5,
self._desktop.screenGeometry().height()
)
# 窗口弹出结束位置
self._endPos = QPoint(
self._desktop.screenGeometry().width() - self.width() - 5,
self._desktop.availableGeometry().height() - self.height() - 5
)
# 初始化位置到右下角
self.move(self._startPos)
# 动画
self.animation = QPropertyAnimation(self, b"pos")
self.animation.finished.connect(self.onAnimationEnd)
self.animation.setDuration(1000) # 1s
# 弹回定时器
self._timer = QTimer(self, timeout=self.closeAnimation)
def show(self, title="", content="", timeout=5000):
self._timer.stop() # 停止定时器,防止第二个弹出窗弹出时之前的定时器出问题
self.hide() # 先隐藏
self.move(self._startPos) # 初始化位置到右下角
super(WindowNotify, self).show()
self.setTitle(title).setContent(content).setTimeout(timeout)
return self
def showAnimation(self):
print("showAnimation isShow = True")
# 显示动画
self.isShow = True
self.animation.stop()#先停止之前的动画,重新开始
self.animation.setStartValue(self.pos())
self.animation.setEndValue(self._endPos)
self.animation.start()
# 弹出5秒后,如果没有焦点则弹回去
self._timer.start(self._timeout)
# QTimer.singleShot(self._timeout, self.closeAnimation)
def closeAnimation(self):
print("closeAnimation hasFocus", self.hasFocus())
# 关闭动画
if self.hasFocus():
# 如果弹出后倒计时5秒后还有焦点存在则失去焦点后需要主动触发关闭
self._timeouted = True
return # 如果有焦点则不关闭
self.isShow = False
self.animation.stop()
self.animation.setStartValue(self.pos())
self.animation.setEndValue(self._startPos)
self.animation.start()
def onAnimationEnd(self):
# 动画结束
print("onAnimationEnd isShow", self.isShow)
if not self.isShow:
print("onAnimationEnd close()")
self.close()
print("onAnimationEnd stop timer")
self._timer.stop()
print("onAnimationEnd close and emit signal")
self.SignalClosed.emit()
def enterEvent(self, event):
super(WindowNotify, self).enterEvent(event)
# 设置焦点(好像没啥用,不过鼠标点击一下后,该方法就有用了)
print("enterEvent setFocus Qt.MouseFocusReason")
self.setFocus(Qt.MouseFocusReason)
def leaveEvent(self, event):
super(WindowNotify, self).leaveEvent(event)
# 取消焦点
print("leaveEvent clearFocus")
self.clearFocus()
if self._timeouted:
QTimer.singleShot(1000, self.closeAnimation)
if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication, QHBoxLayout
app = QApplication(sys.argv)
window = QWidget()
notify = WindowNotify(parent=window)
layout = QHBoxLayout(window)
b1 = QPushButton(
"弹窗1", window, clicked=lambda: notify.show(content=b1.text()).showAnimation())
b2 = QPushButton(
"弹窗2", window, clicked=lambda: notify.show(content=b2.text()).showAnimation())
layout.addWidget(b1)
layout.addWidget(b2)
window.show()
sys.exit(app.exec_())