本来想直接继承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)



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

2433

被折叠的 条评论
为什么被折叠?



