添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Qt 实现带阴影的QMessagebox

在实际项目里面使用到了 QMessageBox 做一个弹窗,最开始是样式不是需要的样式,就去找了一下 QMessageBox 的样式表,一般来说可以使用 findChild() 来找到这个控件中的一切子控件,Qt的许多控件都是由一些其他的控件组合在一起。
下面这个函数是来自博主
公孙二狗

void MainWidget::dumpStructure(const QObject *obj, int spaceCount) {
    qDebug() << QString("%1%2 : %3")
                .arg("", spaceCount)
                .arg(obj->metaObject()->className())
                .arg(obj->objectName());
    QObjectList list = obj->children();
    foreach (QObject * child, list) {
        dumpStructure(child, spaceCount + 4);

就是一个递归函数,来一直遍历子控件的内容,下面是输出的结果

"QMessageBox : "
"    QLabel : qt_msgboxex_icon_label"
"    QGridLayout : "
"    QLabel : qt_msgbox_label"
"    QDialogButtonBox : qt_msgbox_buttonbox"
"        QHBoxLayout : "

这表明,QMessageBox里面有QLable -> qt_msgboxex_icon_label这个是指框里的图标、QLabel -> qt_msgbox_label这个就是里面文字,QDialogButtonBox -> qt_msgbox_buttonbox这个就是按钮,例如下图:

下图是我设置的样式表,这样式表部分参考自QSS 自定义QMessageBox

/* =============================================== */
/* QMessageBox                                     */
/* =============================================== */
/*设置背景*/
 QMessageBox
    background-color: rgba(51, 153, 251, 1);
    border-radius: 3px;
    width: 240px;
    height: 180px;
/*设置QMessageBox的文字内容*/
QMessageBox QLabel#qt_msgbox_label { /* textLabel */
        color: rgba(255, 255, 255, 1);
        background-color: transparent;
        min-width: 240px; /* textLabel设置最小宽度可以相应的改变QMessageBox的最小宽度 */
        min-height: 80px; /* textLabel和iconLabel高度保持一致 */
/*设置图标*/
QMessageBox QLabel#qt_msgboxex_icon_label { /* iconLabel */
        width: 80px;
        height: 80px; /* textLabel和iconLabel高度保持一致 */
/*设置按钮样式*/
QMessageBox QPushButton
    background-color: rgba(51, 153, 251, 1);
    width: 50px;
    height: 20px;
    color: rgba(0, 0, 0, 1);
    font: 10pt "Microsoft YaHei";
    border-style: inset;
    border-color: rgba(0, 74, 169, 1);
    border-width: 1;

这是效果图:
在这里插入图片描述

但是你会发现一个问题,就是这个对话框的标题的背景什么的并不可以修改,这个标题栏的样式是跟随系统的。所以这个时候就需要自己实现一个对话框来解决这些问题。下面是我设计的对话框,参考了大佬一去二三里的博客。

#ifndef SHADOWMESSAGEBOX_H
#define SHADOWMESSAGEBOX_H
#include <QWidget>
#include <QLabel>
#include <QIcon>
#include <QHBoxLayout>
#include <QPushButton>
#include <QGraphicsDropShadowEffect>
#include "titlebar.h"
class ShadowMessageBox : public QWidget
    Q_OBJECT
public:
    enum Icon {
            // keep this in sync with QMessageDialogOptions::Icon
            NoIcon = 0,
            Information = 1,
            Warning = 2,
            Critical = 3,
            Question = 4
    ShadowMessageBox(QWidget * parent);
    ShadowMessageBox(QWidget * parent, const QString &title, const QString &text, ShadowMessageBox::Icon icon=Information);
    static void information(QWidget * parent, const QString &title, const QString &text);
    static void critical(QWidget * parent, const QString &title, const QString &text);
private:
    QWidget * m_widg;
    TitleBar * m_pTitleBar;
    QVBoxLayout *m_pLayout;
    QLabel * m_msgIcon;
    QLabel * m_msgText;
    QHBoxLayout * m_hlabLayout;
    QHBoxLayout * m_hbtnLayout;
    QSpacerItem * m_horizontalSpacer;
    QSpacerItem * m_horizontalSpacer_2;
    QPushButton * m_btnOK;
    QHBoxLayout * m_hpLayout;
    QGraphicsDropShadowEffect *m_pEffect;
//    QMap<ShadowMessageBox::Icon, QString> m_ico{{NoIcon, ""}};
#endif // SHADOWMESSAGEBOX_H
#include "shadowmessagebox.h"
ShadowMessageBox::ShadowMessageBox(QWidget *parent)
    :QWidget(parent)
    this->setAttribute(Qt::WA_TranslucentBackground);
    this->setAttribute(Qt::WA_DeleteOnClose);
    this->setWindowFlags(this->windowFlags()|Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint |Qt::Dialog);
    this->setWindowModality(Qt::WindowModal);
    this->setVisible(true);
    m_widg = new QWidget(this);
    m_pTitleBar = new TitleBar(m_widg);
    m_widg->installEventFilter(m_pTitleBar);
    m_widg->setWindowTitle("QMessageBox");
    m_widg->setWindowIcon(QIcon("D:\\1.ico"));
    QPalette pal(palette());
    pal.setColor(QPalette::Background, QColor(51, 153, 251, 255));
    m_widg->setAutoFillBackground(true);
    m_widg->setPalette(pal);
    m_pLayout = new QVBoxLayout(m_widg);
    m_pLayout->addWidget(m_pTitleBar);
    m_pLayout->addStretch();
    m_pLayout->setSpacing(0);
    m_pLayout->setContentsMargins(0, 0, 0, 5);
    m_widg->setLayout(m_pLayout);
    m_msgIcon  = new QLabel(m_widg);
    m_msgIcon->setFixedSize(48,48);
    m_msgIcon->setPixmap(QPixmap("D:/images/CG.png", "png"));
    m_msgText = new QLabel(m_widg);
    m_msgText->setStyleSheet("font: 20pt \"Microsoft YaHei\";color: white;");
    m_msgText->setText("导出成功");
    m_hlabLayout = new QHBoxLayout();
    m_hlabLayout->addWidget(m_msgIcon);
    m_hlabLayout->addWidget(m_msgText);
    m_hlabLayout->setContentsMargins(5,0,5,0);
    m_pLayout->addLayout(m_hlabLayout);
    m_hbtnLayout= new QHBoxLayout();
    m_horizontalSpacer= new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_hbtnLayout->addItem(m_horizontalSpacer);
    m_btnOK = new QPushButton(m_widg);
    m_btnOK->setFixedSize(72,25);
    m_btnOK->setText("OK");
    m_btnOK->setStyleSheet("border:1px solid rgba(0, 74, 169, 1);font: 10px \"Microsoft YaHei\";color: rgba(0, 0, 0, 1)");
    m_hbtnLayout->addWidget(m_btnOK);
    m_horizontalSpacer_2= new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_hbtnLayout->addItem(m_horizontalSpacer_2);
    connect(m_btnOK, &QPushButton::clicked, this, &QWidget::close);
    m_pLayout->addLayout(m_hbtnLayout);
    m_hpLayout = new QHBoxLayout(this);
    m_hpLayout->addWidget(m_widg);
    m_hpLayout->setContentsMargins(20, 20, 20, 20);
    m_pEffect = new QGraphicsDropShadowEffect(m_widg);
    m_pEffect->setOffset(0, 0);
    m_pEffect->setColor(QColor(QStringLiteral("black")));
    m_pEffect->setBlurRadius(30);
    m_widg->setGraphicsEffect(m_pEffect);
ShadowMessageBox::ShadowMessageBox(QWidget *parent, const QString &title, const QString &text , ShadowMessageBox::Icon icon)
    :QWidget(parent)
    this->setAttribute(Qt::WA_TranslucentBackground);
    this->setAttribute(Qt::WA_DeleteOnClose);
    this->setWindowFlags(this->windowFlags()|Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint |Qt::Dialog);
    this->setWindowModality(Qt::WindowModal);
    this->setVisible(true);
    m_widg = new QWidget(this);
    m_pTitleBar = new TitleBar(m_widg);
    m_widg->installEventFilter(m_pTitleBar);
    m_widg->setWindowTitle(title);
    m_widg->setWindowIcon(this->windowIcon());
    QPalette pal(palette());
    pal.setColor(QPalette::Background, QColor(51, 153, 251, 255));
    m_widg->setAutoFillBackground(true);
    m_widg->setPalette(pal);
    m_pLayout = new QVBoxLayout(m_widg);
    m_pLayout->addWidget(m_pTitleBar);
    m_pLayout->addStretch();
    m_pLayout->setSpacing(0);
    m_pLayout->setContentsMargins(0, 0, 0, 5);
    m_widg->setLayout(m_pLayout);
    m_msgIcon  = new QLabel(m_widg);
    m_msgIcon->setFixedSize(48,48);
    if (icon == ShadowMessageBox::Icon::Information) {
        m_msgIcon->setPixmap(QPixmap(":/images/images/TS.png"));
    else if (icon == ShadowMessageBox::Icon::Critical) {
        m_msgIcon->setPixmap(QPixmap(":/images/images/CW.png"));
    m_msgText = new QLabel(m_widg);
    m_msgText->setStyleSheet("font: 20pt \"Microsoft YaHei\";color: white;");
    m_msgText->setText(text);
    m_hlabLayout = new QHBoxLayout();
    m_hlabLayout->addWidget(m_msgIcon);
    m_hlabLayout->addWidget(m_msgText);
    m_hlabLayout->setContentsMargins(5,0,5,0);
    m_pLayout->addLayout(m_hlabLayout);
    m_hbtnLayout= new QHBoxLayout();
    m_horizontalSpacer= new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_hbtnLayout->addItem(m_horizontalSpacer);
    m_btnOK = new QPushButton(m_widg);
    m_btnOK->setFixedSize(72,25);
    m_btnOK->setText("OK");
    m_btnOK->setStyleSheet("border:1px solid rgba(0, 74, 169, 1);font: 10px \"Microsoft YaHei\";color: rgba(0, 0, 0, 1)");
    m_hbtnLayout->addWidget(m_btnOK);
    m_horizontalSpacer_2= new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_hbtnLayout->addItem(m_horizontalSpacer_2);
    connect(m_btnOK, &QPushButton::clicked, this, &QWidget::close);
    m_pLayout->addLayout(m_hbtnLayout);
    m_hpLayout = new QHBoxLayout(this);
    m_hpLayout->addWidget(m_widg);
    m_hpLayout->setContentsMargins(20, 20, 20, 20);
    m_pEffect = new QGraphicsDropShadowEffect(m_widg);
    m_pEffect->setOffset(0, 0);
    m_pEffect->setColor(QColor(QStringLiteral("black")));
    m_pEffect->setBlurRadius(30);
    m_widg->setGraphicsEffect(m_pEffect);
void ShadowMessageBox::information(QWidget *parent, const QString &title, const QString &text)
    ShadowMessageBox  * msgBox = new ShadowMessageBox(parent , title, text, ShadowMessageBox::Icon::Information);
void ShadowMessageBox::critical(QWidget *parent, const QString &title, const QString &text)
    ShadowMessageBox * msgBox = new ShadowMessageBox(parent , title, text, ShadowMessageBox::Icon::Critical);

调用方法为:

	ShadowMessageBox::information(this, "提示", "提示");
	// 这个this必须指定

关于阴影的部分,我也是折腾了好一会,具体结构图如下:
在这里插入图片描述
本来的是想直接放在MainWindow下的,但是这个要设置窗口背景透明,这样就会导致其他的样式不对,所以就依附在一个新创建的widget上。代码如下:

// 首先你要把这个最外层的widget设置成透明
	this->setAttribute(Qt::WA_TranslucentBackground);
    this->setAttribute(Qt::WA_DeleteOnClose);
    this->setWindowFlags(this->windowFlags()|Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint |Qt::Dialog);
    this->setWindowModality(Qt::WindowModal);
    this->setVisible(true);
// 然后要设置一个布局管理器,来设置间距。以达到显示阴影的目的
	m_hpLayout = new QHBoxLayout(this);
    m_hpLayout->addWidget(m_widg);
    m_hpLayout->setContentsMargins(20, 20, 20, 20); // 这里是设置上下左右的阴影宽度
// 这里就是给带标题栏的那个widget添加阴影
    m_pEffect = new QGraphicsDropShadowEffect(m_widg);
    m_pEffect->setOffset(0, 0);
    m_pEffect->setColor(QColor(QStringLiteral("black")));
    m_pEffect->setBlurRadius(30); // 设置阴影圆角
    m_widg->setGraphicsEffect(m_pEffect);

效果图如下:
在这里插入图片描述

这个阴影部分可以参考以下博客
标题栏
阴影
阴影
九宫格缩放图片原理
阴影(附带九宫格)
以上TitleBar这个类,是博主一去、二三里大神的博文中的一个标题栏的类,请移步Qt 之自定义界面(添加自定义标题栏),然后还参考了Qt官方的QMessageBox的设计,写出来了。本人代码水平不是特别的好,还有许多没有完善,里面应该有挺多的问题,只是给大家提供一个思路,烦请大家多多指正。