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

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_())