用pyqt自定义一个弹框

  • Post author:
  • Post category:其他




思路

网上没有合适的弹框公开,只能自己写个,虽然比较简单,但是从零开始思考怎么实现还是需要时间的。



窗口的实现

使用

QDialog

设计一个窗口。

注意:这里也可以用

QWidget

,但是你得保证父控件不是QWidget,否则设置的动画会不显示

class MessageBox(QDialog):
    def __init__(self, *args, **kwargs):
        super(MessageBox, self).__init__(*args, **kwargs)
        self.resize(300, 80)
        self.setMinimumSize(300, 80)
        # Qt.Window 声明这是一个窗口,如果没有Qt会显示不出来
        # Qt.WindowType.FramelessWindowHint 去掉系统自带的边框
        # Qt.WindowType.WindowStaysOnTopHint 将窗口置于最上层
        self.setWindowFlags(Qt.Window | Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint)
        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)  # 将界面属性设置为半透明

        self.animation = None
        # 如果有父控件,弹框显示到父控件中间
        if self.parent():
            self.move(self.parent().frameGeometry().center().x() - self.frameGeometry().width() // 2,
                      self.parent().frameGeometry().center().y() - self.parent().height() // 2 + 100)



半透明效果

Qt自带的设置透明度无法生效,故使用qss实现


rgba()

可以设置单个控件的透明度,设置

QFrame

的透明度,

QFrame

上的控件背景为空,或者

rgba

的最后一个值为0,否则会出现子控件不透明的情况

        self.setStyleSheet("*{\n"
                           "    font: 12pt \"黑体\";\n"
                           "}\n"
                           "#frame{\n"
                           "    background-color: rgb(0, 0, 0, 0.6);\n"
                           "    border-radius: 20px;\n"
                           "}\n"
                           "#label{\n"
                           "    background-color: none;\n"
                           "    border: none;\n"
                           "}\n"
                           "#pushButton{\n"
                           "    background-color: none;\n"
                           "    border: none;\n"
                           "    color: rgb(255, 255, 255, 0.8);\n"
                           "    text-align: center;\n"
                           "}")



控件选择

使用

QVBoxLayout

自适应窗口大小,

QLabel

显示gif图片等,

QPushButton

显示图标与文字

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.frame = QFrame(self)
        self.frame.setFrameShape(QFrame.StyledPanel)
        self.frame.setFrameShadow(QFrame.Raised)
        self.frame.setObjectName("frame")
        self.verticalLayout_2 = QVBoxLayout(self.frame)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QLabel(self.frame)
        self.label.setMinimumSize(QSize(50, 50))
        self.label.setMaximumSize(QSize(50, 50))
        self.label.setObjectName("label")

        self.pushButton = QPushButton(self.frame)
        self.pushButton.setMinimumSize(QSize(200, 35))
        self.pushButton.setMaximumSize(QSize(10000, 30))
        self.pushButton.setObjectName("pushButton")

        self.verticalLayout_2.addLayout(self.horizontalLayout)
        self.verticalLayout.addWidget(self.frame)
    def addMsgIconAndText(self, icon: QIcon() = None, text: str = None):
        """
        添加图标和文本
        :param icon:
        :param text:
        :return:
        """
        if icon:
            self.pushButton.setIcon(icon)
            self.pushButton.setIconSize(QSize(50, 50))
        if text:
            self.pushButton.setText(text)
        self.pushButton.adjustSize()
        self.horizontalLayout.addWidget(self.pushButton)

   def addMsgGif(self, gif_path):
        """
        添加gif文件
        :param gif_path:
        :return:
        """
        movie = QMovie(gif_path)
        movie.setScaledSize(QSize(50, 50))
        self.label.setMovie(movie)
        movie.start()
        movie.setSpeed(100)
        self.horizontalLayout.addWidget(self.label)



自动关闭弹框

使用

QTimer

设置一个定时器,弹框自动关闭

        self.timer = QTimer()
        self.timer.timeout.connect(self.close)
    def setTimerMsec(self, msec: int):
        self.timer.start(msec * 1000)



边框阴影

def shadowEffect(obj):
    """
    边框阴影
    :param obj:
    :return:
    """
    shadow = QGraphicsDropShadowEffect()
    shadow.setBlurRadius(10)
    shadow.setColor(QColor(64, 64, 64))
    shadow.setOffset(0, 0)
    obj.setGraphicsEffect(shadow)



关闭动画

    def closeEvent(self, event):
        """
        关闭动画
        :param event:
        :return:
        """
        if self.animation is None:
            self.animation = QPropertyAnimation(self, b'windowOpacity')
            self.animation.setDuration(1000)
            self.animation.setStartValue(1)
            self.animation.setEndValue(0)
            self.animation.finished.connect(self.close)
            self.animation.start()
            event.ignore()



完整代码

import sys

from PyQt5.QtCore import *
from PyQt5.QtGui import QColor, QIcon, QMovie, QMoveEvent
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QFrame, QHBoxLayout, QLabel, QPushButton, QGraphicsDropShadowEffect, \
    QApplication


def shadowEffect(obj):
    """
    边框阴影
    :param obj:
    :return:
    """
    shadow = QGraphicsDropShadowEffect()
    shadow.setBlurRadius(10)
    shadow.setColor(QColor(64, 64, 64))
    shadow.setOffset(0, 0)
    obj.setGraphicsEffect(shadow)


class MessageBox(QDialog):
    def __init__(self, *args, **kwargs):
        super(MessageBox, self).__init__(*args, **kwargs)
        self.resize(300, 80)
        self.setMinimumSize(300, 80)
        # Qt.Window 声明这是一个窗口,如果没有Qt会显示不出来
        # Qt.WindowType.FramelessWindowHint 去掉系统自带的边框
        # Qt.WindowType.WindowStaysOnTopHint 将窗口置于最上层
        self.setWindowFlags(Qt.Window | Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint)
        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)  # 将界面属性设置为半透明

        self.setContentsMargins(5, 5, 5, 5)
        self.animation = None
        # 如果有父控件,弹框显示到父控件中间
        if self.parent():
            self.move(self.parent().frameGeometry().center().x() - self.frameGeometry().width() // 2,
                      self.parent().frameGeometry().center().y() - self.parent().height() // 2 + 100)

        self.setStyleSheet("*{\n"
                           "    font: 12pt \"黑体\";\n"
                           "}\n"
                           "#frame{\n"
                           "    background-color: rgb(0, 0, 0, 0.6);\n"
                           "    border-radius: 35px;\n"
                           "}\n"
                           "#label{\n"
                           "    background-color: none;\n"
                           "    border: none;\n"
                           "}\n"
                           "#pushButton{\n"
                           "    background-color: none;\n"
                           "    border: none;\n"
                           "    color: rgb(255, 255, 255, 0.8);\n"
                           "    text-align: center;\n"
                           "}")

        self.timer = QTimer()
        self.timer.timeout.connect(self.close)
        
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.frame = QFrame(self)
        self.frame.setFrameShape(QFrame.StyledPanel)
        self.frame.setFrameShadow(QFrame.Raised)
        self.frame.setObjectName("frame")
        self.verticalLayout_2 = QVBoxLayout(self.frame)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QLabel(self.frame)
        self.label.setMinimumSize(QSize(50, 50))
        self.label.setMaximumSize(QSize(50, 50))
        self.label.setObjectName("label")

        self.pushButton = QPushButton(self.frame)
        self.pushButton.setMinimumSize(QSize(200, 35))
        self.pushButton.setMaximumSize(QSize(10000, 30))
        self.pushButton.setObjectName("pushButton")

        self.verticalLayout_2.addLayout(self.horizontalLayout)
        self.verticalLayout.addWidget(self.frame)
        shadowEffect(self.frame)

        self.show()

    def closeEvent(self, event):
        """
        关闭动画
        :param event:
        :return:
        """
        if self.animation is None:
            self.animation = QPropertyAnimation(self, b'windowOpacity')
            self.animation.setDuration(1000)
            self.animation.setStartValue(1)
            self.animation.setEndValue(0)
            self.animation.finished.connect(self.close)
            self.animation.start()
            event.ignore()

    def addMsgIconAndText(self, icon: QIcon() = None, text: str = None):
        """
        添加图标和文本
        :param icon:
        :param text:
        :return:
        """
        if icon:
            self.pushButton.setIcon(icon)
            self.pushButton.setIconSize(QSize(50, 50))
        if text:
            self.pushButton.setText(text)
        self.pushButton.adjustSize()
        self.horizontalLayout.addWidget(self.pushButton)

    def addMsgGif(self, gif_path):
        """
        添加gif文件
        :param gif_path:
        :return:
        """
        movie = QMovie(gif_path)
        movie.setScaledSize(QSize(50, 50))
        self.label.setMovie(movie)
        movie.start()
        movie.setSpeed(100)
        self.horizontalLayout.addWidget(self.label)

    def setTimerMsec(self, msec: int):
        """
        设置自动关闭时间
        :param msec:
        :return:
        """
        self.timer.start(msec * 1000)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = MessageBox()
    win.addMsgIconAndText(text='测试')
    win.setTimerMsec(2)

    win.show()
    sys.exit(app.exec_())



版权声明:本文为weixin_54217201原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。