PyQt5实现Toast提示功能

        最近用PyQt5开发PC上位机软件,想实现点击"保存"按钮后有成功或失败的提示,但是找了一圈发现PyQt5没有类似Android的Toast的提示控件,所以需要自定义实现,废话不多说,源码如下:

# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QSizePolicy
from PyQt5.QtWidgets import QDesktopWidget
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtGui import QPainter, QPaintEvent, QBrush
from PyQt5.QtCore import QTimer, QSize, QPropertyAnimation
from PyQt5.Qt import Qt


class Toast(QWidget):
    style = """#LabelMessage{color:white;font-family:Microsoft YaHei;}"""

    def __init__(self, message='', timeout=1500, parent=None):
        """
        @param message: 提示信息
        @param timeout: 窗口显示时长
        @param parent: 父窗口控件
        """
        super(Toast, self).__init__()
        self.parent = parent
        # 除了成功之外其他消息图标一律使用错误图标(有局限性:成功的具体信息有很多种,但这里没办法区分,待改)
        self.timer = QTimer()
        # 由于不知道动画结束的事件,所以借助QTimer来关闭窗口,动画结束就关闭窗口,所以这里的事件要和动画时间一样
        self.timer.singleShot(timeout, self.close)  # singleShot表示timer只会启动一次

        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SubWindow)
        # self.setWindowOpacity(0.9)  # 设置窗口透明度
        self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口透明
        self.setObjectName('Toast')
        # self.setFixedSize(QSize(220, 100))
        self.setMinimumSize(QSize(220, 100))
        self.setMaximumSize(QSize(220, 180))

        layout = QHBoxLayout()
        layout.setContentsMargins(20, -1, 20, -1)
        layout.setObjectName("HorizontalLayout")
        self.setLayout(layout)

        self.initUi(layout, message)
        self.createAnimation(timeout)

        self.setStyleSheet(Toast.style)
        self.center()

    def initUi(self, layout, message):
        messageLabel = QLabel()
        # 实现QLabel自动换行
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(messageLabel.sizePolicy().hasHeightForWidth())
        messageLabel.setSizePolicy(sizePolicy)
        messageLabel.setWordWrap(True)
        messageLabel.setText(message)
        messageLabel.setTextFormat(Qt.AutoText)
        messageLabel.setScaledContents(True)
        messageLabel.setObjectName("LabelMessage")
        messageLabel.setAlignment(Qt.AlignCenter)
        layout.addWidget(messageLabel)

    def paintEvent(self, a0: QPaintEvent):
        qp = QPainter()
        qp.begin(self)  # 不能掉,不然没效果
        qp.setRenderHints(QPainter.Antialiasing, True)  # 抗锯齿
        qp.setBrush(QBrush(Qt.black))
        qp.setPen(Qt.transparent)
        rect = self.rect()
        rect.setWidth(rect.width() - 1)
        rect.setHeight(rect.height() - 1)
        qp.drawRoundedRect(rect, 15, 15)
        qp.end()

    def createAnimation(self, timeout):
        # 1.定义一个动画
        self.animation = QPropertyAnimation(self, b'windowOpacity')
        self.animation.setTargetObject(self)
        # 2.设置属性值
        self.animation.setStartValue(0)
        self.animation.setKeyValueAt(0.2, 0.7)  # 设置插值0.3 表示单本次动画时间的0.3处的时间点
        self.animation.setKeyValueAt(0.8, 0.7)  # 设置插值0.8 表示单本次动画时间的0.3处的时间点
        self.animation.setEndValue(0)
        # 3.设置时长
        self.animation.setDuration(timeout)
        # 4.启动动画
        self.animation.start()

    def center(self):
        if self.parent is not None:
            xPos = self.parent.x()+int((self.parent.width() - self.width()) / 2)
            yPos = self.parent.y()+int((self.parent.height() - self.height()) / 2 + 40)
            self.move(xPos, yPos)
        else:
            # 屏幕居中
            screen = QDesktopWidget().screenGeometry()
            size = self.geometry()
            self.move(int((screen.width() - size.width()) / 2),
                      int((screen.height() - size.height()) / 2) + 40)


class Window(QWidget):

    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)
        self.resize(400, 400)
        layout = QVBoxLayout(self)
        layout.addWidget(QPushButton('显示Toast', self, clicked=self.showToast))

    def showToast(self):
        Toast("保存成功", parent=self).show()


if __name__ == '__main__':
    import sys
    from PyQt5.QtWidgets import QApplication

    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())

你可能感兴趣的:(PyQt5开发应用软件,动画,qt,开发语言)