PyQt自定义MessageBox

本文介绍了如何在PyQt中创建自定义的MessageBox,避免直接继承带来的窗口样式问题。通过布局管理和图标替换,实现了符合需求的弹窗效果,推荐使用iconfont网站获取自定义图标。

本来想直接继承QMessageBox,但是继承之后窗口的大小、stylesheet什么的都不太好搞定,于是重新做了一个,参考:QT自定义messagebox弹窗,使用PyQt重写

布局
在这里插入图片描述
自动生成代码

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(400, 165)
        Dialog.setStyleSheet("QDialog {\n"
"    background-color:white;\n"
"}\n"
"QPushButton {\n"
"    border:2px solid rgb(0, 0, 127);\n"
"    padding:5px;\n"
"    border-radius:15px;\n"
"    color:#000000;\n"
"    background-color:transparent;\n"
"    font-family: \'Microsoft YaHei Ui\';\n"
"    font-size: 9pt;\n"
"    font-weight: bold;\n"
"}\n"
"QPushButton:hover {\n"
"    color:#0078d7;\n"
"    background:rgb(255, 255, 255);\n"
"    border:2px solid #0078d7;\n"
"}\n"
"QPushButton:pressed {\n"
"    color:#000000;\n"
"    background:#B8C6D1;\n"
"}\n"
"")
        self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
        self.verticalLayout.setObjectName("verticalLayout")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        spacerItem = QtWidgets.QSpacerItem(15, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.pbt_icon = QtWidgets.QPushButton(Dialog)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pbt_icon.sizePolicy().hasHeightForWidth())
        self.pbt_icon.setSizePolicy(sizePolicy)
        self.pbt_icon.setMinimumSize(QtCore.QSize(68, 64))
        self.pbt_icon.setStyleSheet("background-color: transparent;\n"
"border:none;")
        self.pbt_icon.setText("")
        self.pbt_icon.setIconSize(QtCore.QSize(64, 64))
        self.pbt_icon.setFlat(True)
        self.pbt_icon.setObjectName("pbt_icon")
        self.horizontalLayout.addWidget(self.pbt_icon)
        spacerItem1 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem1)
        self.lb_text = QtWidgets.QLabel(Dialog)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.lb_text.sizePolicy().hasHeightForWidth())
        self.lb_text.setSizePolicy(sizePolicy)
        self.lb_text.setMinimumSize(QtCore.QSize(250, 0))
        font = QtGui.QFont()
        font.setFamily("Microsoft YaHei UI")
        self.lb_text.setFont(font)
        self.lb_text.setStyleSheet("QLabel {\n"
"    background-color:transparent;\n"
"}")
        self.lb_text.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
        self.lb_text.setWordWrap(True)
        self.lb_text.setObjectName("lb_text")
        self.horizontalLayout.addWidget(self.lb_text)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.hlayout = QtWidgets.QHBoxLayout()
        self.hlayout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
        self.hlayout.setObjectName("hlayout")
        spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.hlayout.addItem(spacerItem2)
        self.verticalLayout.addLayout(self.hlayout)
        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.lb_text.setText(_translate("Dialog", "提示框"))

MessageBox

from PyQt5.QtWidgets import QDialog, QApplication, QPushButton, QSizePolicy
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QPixmap, QIcon
from Ui_MessageBox import Ui_Dialog
import sys

class MessageBox(QDialog):
    """ 自定义MessageBox,继承自QDialog     
    其中有3个static method可用: information, warning, error,使用方法与QMessageBox基本一致
    Args:   
        parent: 父窗口
        title: MessageBox窗口标题 Window Title
        text: 消息文本
        btype: 按钮,有五种类型按钮:YES, NO, CANCLE, CLOSE, OK
        default: 默认按钮,默认值为YES
    """
    # 仅支持这几个按键
    YES    = 0x01
    NO     = 0x02
    CANCEL = 0x04
    CLOSE  = 0x08
    OK     = 0x10
    # 返回值
    retValue = 0

    def __init__(self, parent, title: str, text: str, btype=YES, default=YES):
        super().__init__(parent)
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.setWindowModality(Qt.ApplicationModal)
        self.setAttribute(Qt.WA_QuitOnClose, True)
        self.setWindowTitle(title)
        self.btnList = {}
        self.ui.lb_text.setText(text)
        self.create_button(btype)
        self.set_default_btn(btype, default)

    def create_button(self, btype):
        # 如果按钮是yes
        if btype & MessageBox.YES == MessageBox.YES:
            self.yesbtn = QPushButton(self)
            self.set_button(self.yesbtn, u'Yes')
            self.btnList[MessageBox.YES] = self.yesbtn
            self.yesbtn.clicked.connect(self.btn_yes)
        # 如果按钮是no
        if btype & MessageBox.NO == MessageBox.NO:
            self.nobtn = QPushButton(self)
            self.set_button(self.nobtn, u'No')
            self.btnList[MessageBox.NO] = self.nobtn
            self.nobtn.clicked.connect(self.btn_no)
        # 如果按钮是cancel
        if btype & MessageBox.CANCEL == MessageBox.CANCEL:
            self.cancelbtn = QPushButton(self)
            self.set_button(self.cancelbtn, u'Cancel')
            self.btnList[MessageBox.CANCEL] = self.cancelbtn
            self.cancelbtn.clicked.connect(self.btn_cancel)
        # 如果按钮是close
        if btype & MessageBox.CLOSE == MessageBox.CLOSE:
            self.closebtn = QPushButton(self)
            self.set_button(self.closebtn, u'Close')
            self.btnList[MessageBox.CLOSE] = self.closebtn
            self.closebtn.clicked.connect(self.btn_close)
        # 如果按钮是ok
        if btype & MessageBox.OK == MessageBox.OK:
            self.okbtn = QPushButton(self)
            self.set_button(self.okbtn, u'Ok')
            self.btnList[MessageBox.OK] = self.okbtn
            self.okbtn.clicked.connect(self.btn_ok)

    def set_default_btn(self, btype, default):
        # default键必须是一个独立的按键
        if default not in {MessageBox.YES, MessageBox.NO, MessageBox.CANCEL, MessageBox.OK, MessageBox.CLOSE}:
            return
        if default & btype != 0:
            self.btnList[default].setDefault(True)

    def set_button(self, btn:QPushButton, text:str):
        # 设置按钮的一些参数
        btn.setText(text)
        btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        btn.setFixedSize(QSize(95, 35))
        self.ui.hlayout.addWidget(btn)

    def btn_yes(self):
        MessageBox.retValue = MessageBox.YES
        self.close()
        
    def btn_no(self):
        MessageBox.retValue = MessageBox.NO
        self.close()
        
    def btn_cancel(self):
        MessageBox.retValue = MessageBox.CANCEL
        self.close()
        
    def btn_close(self):
        MessageBox.retValue = MessageBox.CLOSE
        self.close()
        
    def btn_ok(self):
        MessageBox.retValue = MessageBox.OK
        self.close()

    def ret_val(self):
        return MessageBox.retValue

    # 使用时调用的静态方法
    @staticmethod
    def information(parent, title, text, btype=YES, default=YES):
        box = MessageBox(parent, title, text, btype, default)
        box.ui.pbt_icon.setIcon(QIcon(QPixmap(":/mainui/icon/notify.png")))
        box.exec()
        return box.ret_val()

    @staticmethod
    def warning(parent, title, text, btype=YES, default=YES):
        box = MessageBox(parent, title, text, btype, default)
        box.ui.pbt_icon.setIcon(QIcon(QPixmap(":/mainui/icon/warning.png")))
        box.exec()
        return box.ret_val()

    @staticmethod
    def error(parent, title, text, btype=YES, default=YES):
        box = MessageBox(parent, title, text, btype, default)
        box.ui.pbt_icon.setIcon(QIcon(QPixmap(":/mainui/icon/error.png")))
        box.exec()
        return box.ret_val()

将其中图标换成自己的图标(推荐一个网站:iconfont-阿里巴巴矢量图标库)。
使用

# information
btn = MessageBox.information(None, 'messagebx', '这是一个messagebox', MessageBox.YES | MessageBox.NO, MessageBox.YES)

# warning
btn = MessageBox.warning(None, 'messagebx', '这是一个messagebox', MessageBox.YES | MessageBox.CANCEL | MessageBox.CLOSE)

# error
btn = MessageBox.error(None, 'messagebx', '这是一个messagebox', MessageBox.OK)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值