【QT】如何自定义QMessageBox的窗口大小,通过继承QDialog重新实现美观的弹窗

2023-11-18

1. QMessageBox原有的弹窗

  QMessageBox messageBox(QMessageBox::Question, "提示", "是否保存当前项目?", QMessageBox::Yes | QMessageBox::No);
  messageBox.exec();

在这里插入图片描述
可以看出QMessageBox原有的弹窗看起来非常的不美观,有时候大有时候小,只能使用QMessageBox自带的图标,而且不能自定义窗口的大小,那是因为在源码中将其弹窗大小设置成了比较合适的大小,所以不能自定义改变弹窗大小,如下所示代码都是不起作用的:

   messageBox.setGeometry(800, 300, 450, 225);  //(500,300)设置其位置是有效的,但是设置其大小(450, 225)是无效的
   messageBox.resize(450, 225);                 //resize大小也是无效的

2. 网上第一种方法:通过样式表setStyleSheet实现改变弹窗大小(总体不美观)

  QMessageBox messageBox(QMessageBox::Question, "提示", "是否保存当前项目?", QMessageBox::Yes | QMessageBox::No);
  messageBox.setStyleSheet("QLabel{"
                             "min-width:150px;"
                             "min-height:120px;"
                             "font-size:16px;"
                             "}");
  messageBox.exec();

在这里插入图片描述
可以看出通过样式表的方法也不太美观,其中text没有居中。

3. 网上第二种方法:重写ShowEvent()改变弹窗大小(总体也不美观)

先上代码实现一下:
MyMessageBox.h

#include <QLabel>
#include <QMessageBox>
#include <QWidget>

class MyMessageBox : public QMessageBox {
    Q_OBJECT

public:
    MyMessageBox(Icon icon, const QString& title, const QString& text,
                 StandardButtons buttons, QWidget* parent = 0);
    ~MyMessageBox();

protected:
    void showEvent(QShowEvent* event) override;
};

MyMessageBox.cpp

#include "mymessagebox.h"

MyMessageBox::MyMessageBox(Icon icon, const QString& title, const QString& text,
                           StandardButtons buttons, QWidget* parent) :
    QMessageBox(icon, title, text, buttons, parent) {
}

MyMessageBox::~MyMessageBox() {
}

void MyMessageBox::showEvent(QShowEvent* event) {
    QWidget* textLabel = findChild<QWidget*>("qt_msgbox_label");       //获取源码中text的label组件
    QWidget* iconLabel = findChild<QWidget*>("qt_msgbox_icon_label");  //获取源码中icon的label组件

    if (textLabel != nullptr) {  //使用指针之前先判断是否为空
        textLabel->setMinimumSize(450, 255);
        // textLabel->setFixedSize(450, 255);
    }
    if (iconLabel != nullptr) {
        iconLabel->setMinimumHeight(255);
        iconLabel->setFixedSize(450, 255);
    }
    QMessageBox::showEvent(event);
}

main.cpp

#include <QApplication>

#include "mymessagebox.h"

int main(int argc, char* argv[]) {
    QApplication a(argc, argv);

    MyMessageBox messageBox(QMessageBox::Question, "提示", "是否保存当前项目?", QMessageBox::Yes | QMessageBox::No);
    messageBox.exec();

    //w.show();

    return a.exec();
}

解释一下上面的一些代码
先看一下QMessageBox中的一些源码:
在这里插入图片描述
在对某一个组件设置了setObjectName()属性之后,我们可以通过objectName在外面获得这个组件,如下:

//QLabel继承于QWidget,所以用QWidget*是可以的
QWidget* textLabel = findChild<QWidget*>("qt_msgbox_label");  //获取源码中text的label组件

然后对label组件的大小进行调整,达到调整弹窗大小的目的。可以看到弹窗的大小是改变了,但是还是不美观,主要是图标没有居中,还是处在左上角的位置,如下图所示:

在这里插入图片描述
那对于上面这个问题出现的原因是什么呢?那就看一下QMessageBox中的关于布局Layout的一些源码:
在这里插入图片描述
可以看出在布局时,其icon总是处在第0行第0列的位置,且其Aliment设置的是Top,所以导致了QMessageBox的图标总是在左上角。
所以重写ShowEvent()这种方法也达不到实现美观的弹窗的预期。

4. 最好的办法:继承QDialog重新实现弹窗界面(附完整代码)(v1.0)

重新写一个弹窗TipDialog类,继承于QDialog类。
先看效果:
在这里插入图片描述
直接上代码:
TipDialog.h

#ifndef TIPDIALOG_H
#define TIPDIALOG_H

#include <QDialog>
#include <QDialogButtonBox>
#include <QHBoxLayout>
#include <QIcon>
#include <QLabel>
#include <QMessageBox>
#include <QMetaEnum>
#include <QPixmap>
#include <QPushButton>
#include <QVBoxLayout>

class TipDialog : public QDialog {
    Q_OBJECT

public:
    enum TipIcon {
        NoIcon = 0,
        Information = 1,
        Question = 2,
        Success = 3,
        Warning = 4,
        Critical = 5
    };
    Q_ENUM(TipIcon)  //使用Q_ENUM注册枚举

    enum StandardButton {
        //保持与 QDialogButtonBox::StandardButton 一致,后面在创建按钮时会用到 & 运算
        NoButton = 0x00000000,
        Ok = 0x00000400,
        Save = 0x00000800,
        SaveAll = 0x00001000,
        Open = 0x00002000,
        Yes = 0x00004000,
        YesToAll = 0x00008000,
        No = 0x00010000,
        NoToAll = 0x00020000,
        Abort = 0x00040000,
        Retry = 0x00080000,
        Ignore = 0x00100000,
        Close = 0x00200000,
        Cancel = 0x00400000,
        Discard = 0x00800000,
        Help = 0x01000000,
        Apply = 0x02000000,
        Reset = 0x04000000,
        RestoreDefaults = 0x08000000,

        FirstButton = Ok,
        LastButton = RestoreDefaults
    };
    Q_ENUM(StandardButton)
    Q_DECLARE_FLAGS(StandardButtons, StandardButton)
    Q_FLAG(StandardButtons)

    enum ButtonRole {
        //保持与 QDialogButtonBox::ButtonRole 一致
        InvalidRole = -1,
        AcceptRole,
        RejectRole,
        DestructiveRole,
        ActionRole,
        HelpRole,
        YesRole,
        NoRole,
        ResetRole,
        ApplyRole,

        NRoles
    };

    explicit TipDialog(QWidget* parent = nullptr);
    TipDialog(TipIcon icon, const QString& title, const QString& text, StandardButtons buttons,
              QWidget* parent = nullptr);  //构造函数有默认值的要放后面
    ~TipDialog();

    static void information(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons = Ok);
    static void question(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons = StandardButtons(Yes | No));
    static void success(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons = Ok);
    static void warning(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons = Ok);
    static void critical(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons = Ok);

private:
    void init(const QString& title = QString(), const QString& text = QString());
    void setupLayout();
    QPixmap standardIcon(TipDialog::TipIcon icon);
    void setIcon(TipIcon icon);
    void createButton(StandardButton button);
    void createStandardButtons(StandardButtons buttons);
    void setStandardButtons(StandardButtons buttons);
    //    QString standardTitle(TipDialog::TipIcon icon);
    QString getEnumKey(StandardButton button);
    void addButton(StandardButton button, QDialogButtonBox::ButtonRole buttonRole);

private:
    QLabel* m_pIconLabel;
    QLabel* m_pTextLabel;
    QDialogButtonBox* m_pButtonBox;
    //    QList<QPushButton*> m_pButtonList;
    QString m_text;
};

//在全局任意地方使用"|"操作符计算自定义的枚举量,需要使用Q_DECLARE_OPERATORS_FOR_FLAGS宏
Q_DECLARE_OPERATORS_FOR_FLAGS(TipDialog::StandardButtons)

#endif  // TIPDIALOG_H

TipDialog.cpp

#include "tipdialog.h"

#define fontFamily "宋体"
#define fontSize 12

TipDialog::TipDialog(QWidget* parent) :
    QDialog(parent) {
    init();
}

TipDialog::TipDialog(TipIcon icon, const QString& title, const QString& text, StandardButtons buttons, QWidget* parent) :
    QDialog(parent) {
    init(title, text);
    setWindowTitle(title);
    setIcon(icon);
    setStandardButtons(buttons);
    //    setupLayout();
}

TipDialog::~TipDialog() {}

void TipDialog::information(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons) {
    TipDialog tip(Information, title, text, buttons, parent);
    tip.exec();
}

void TipDialog::question(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons) {
    TipDialog tip(Question, title, text, buttons, parent);
    tip.exec();
}

void TipDialog::success(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons) {
    TipDialog tip(Success, title, text, buttons, parent);
    tip.exec();
}

void TipDialog::warning(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons) {
    TipDialog tip(Warning, title, text, buttons, parent);
    tip.exec();
}

void TipDialog::critical(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons) {
    TipDialog tip(Critical, title, text, buttons, parent);
    tip.exec();
}

void TipDialog::init(const QString& title, const QString& text) {
    resize(QSize(450, 225));
    setWindowIcon(QIcon(":/new/prefix1/Icon/项目.png"));
    setWindowTitle("operation tip...");
    setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);  //设置右上角按钮
    //setAttribute(Qt::WA_DeleteOnClose);                                   //关闭窗口时将窗口释放掉即释放内存

    m_pIconLabel = new QLabel(this);
    m_pIconLabel->setObjectName(QLatin1String("iconLabel"));
    m_pTextLabel = new QLabel(this);
    m_pTextLabel->setObjectName(QLatin1String("textLabel"));
    m_pTextLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);  //label中的内容可用鼠标选择文本复制,链接激活
    m_pTextLabel->setOpenExternalLinks(true);                           //label中的内容若为链接,可直接点击打开
    m_pButtonBox = new QDialogButtonBox(this);
    m_pButtonBox->setObjectName(QLatin1String("buttonBox"));

    if (!title.isEmpty() || !text.isEmpty()) {
        setWindowTitle(title);
        m_pTextLabel->setFont(QFont(fontFamily, fontSize));
        m_pTextLabel->setText(text);
    }

    m_text = text;

    setupLayout();
}

void TipDialog::setupLayout() {
    QHBoxLayout* HLay = new QHBoxLayout;
    HLay->addWidget(m_pIconLabel, 1, Qt::AlignVCenter | Qt::AlignRight);
    HLay->addWidget(m_pTextLabel, 5, Qt::AlignCenter);
    QVBoxLayout* VLay = new QVBoxLayout;
    VLay->addLayout(HLay);
    VLay->addWidget(m_pButtonBox);
    setLayout(VLay);
}

QPixmap TipDialog::standardIcon(TipDialog::TipIcon icon) {
    QPixmap pixmap;
    switch (icon) {
        case TipDialog::Information:
            pixmap.load(":/new/prefix1/Image/Information.png");
            break;
        case TipDialog::Question:
            pixmap.load(":/new/prefix1/Image/Question.png");
            break;
        case TipDialog::Success:
            pixmap.load(":/new/prefix1/Image/Success.png");
            break;
        case TipDialog::Warning:
            pixmap.load(":/new/prefix1/Image/Warning.png");
            break;
        case TipDialog::Critical:
            pixmap.load(":/new/prefix1/Image/Critical.png");
            break;
        default:
            break;
    }
    if (!pixmap.isNull())
        return pixmap;
    return QPixmap();
}

void TipDialog::setIcon(TipDialog::TipIcon icon) {
    m_pIconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    m_pIconLabel->setPixmap(standardIcon(icon));
}

void TipDialog::createButton(StandardButton button) {
    switch (button) {
        case TipDialog::Ok:
            addButton(button, QDialogButtonBox::AcceptRole);
            break;
        case TipDialog::Save:
            addButton(button, QDialogButtonBox::AcceptRole);
            break;
        case TipDialog::Yes:
            addButton(button, QDialogButtonBox::YesRole);
            break;
        case TipDialog::No:
            addButton(button, QDialogButtonBox::NoRole);
            break;
        case TipDialog::Cancel:
            addButton(button, QDialogButtonBox::RejectRole);
            break;
        default:
            break;
    }
}
void TipDialog::createStandardButtons(StandardButtons buttons) {
    //TipDialog::StandardButtons 与 QDialogButtonBox::StandardButtons 的枚举是一样的
    uint i = QDialogButtonBox::FirstButton;  //枚举值为非负整数,使用uint
    while (i <= QDialogButtonBox::LastButton) {
        if (i & buttons) {
            createButton(StandardButton(i));
        }
        i = i << 1;
    }
}

void TipDialog::setStandardButtons(StandardButtons buttons) {
    if (buttons != NoButton)
        createStandardButtons(buttons);
}

//QString TipDialog::standardTitle(TipDialog::TipIcon icon) {
//    QString title;
//    switch (icon) {
//        case TipDialog::Information:
//            title = "Information";
//            break;
//        case TipDialog::Question:
//            title = "Question";
//            break;
//        case TipDialog::Success:
//            title = "Success";
//            break;
//        case TipDialog::Warning:
//            title = "Warning";
//            break;
//        case TipDialog::Critical:
//            title = "Critical";
//            break;
//        default:
//            break;
//    }
//    if (!title.isEmpty())
//        return title;
//    return QString();
//}

QString TipDialog::getEnumKey(StandardButton button) {
    QMetaEnum metaEnum = QMetaEnum::fromType<StandardButton>();  //获取QMetaEnum对象,为了获取枚举值
    QString str = metaEnum.valueToKey(button);
    if (!str.isEmpty())
        return str;
    return QString();
}

void TipDialog::addButton(TipDialog::StandardButton button, QDialogButtonBox::ButtonRole buttonRole) {
    QString buttonText = getEnumKey(button);
    QPushButton* pushButton = m_pButtonBox->addButton(buttonText, buttonRole);
    //    if (pushButton->text() == QLatin1String("Yes") && m_text.contains("save", Qt::CaseSensitive)) {
    //        pushButton->setText("Save");
    //    } else if (pushButton->text() == QLatin1String("Yes") && m_text.contains("delete", Qt::CaseSensitive)) {
    //        pushButton->setText("Delete");
    //    }
    //    m_pButtonList.append(pushButton);
    connect(pushButton, &QPushButton::clicked, this, &TipDialog::close);
}

main.cpp

#include <QApplication>
#include <QMessageBox>

#include "tipdialog.h"

int main(int argc, char* argv[]) {
    QApplication a(argc, argv);

    //TipDialog aa(TipDialog::Question, "Question", "The current project has been modified.\nDo you want to save it?", TipDialog::Yes | TipDialog::No);
    //TipDialog aa(TipDialog::Success, "Success", "Project saved successfully!", TipDialog::Ok);
    //TipDialog aa(TipDialog::Warning, "Warning", "Parsed file not found! Please reconfigure!", TipDialog::Ok);
    TipDialog aa(TipDialog::Critical, "Critical", "Loading failed.Please tryagain!", TipDialog::Ok);

    aa.show();

    return a.exec();
}

注意:需要在Resources文件中自己手动添加icon图片。

5. v1.0的改进:重新实现弹窗界面(附完整代码)(v2.0)

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

增加了许多接口,并且之前v1.0版本添加按钮是自己实现的,其实不需要,直接使用QDialogButtonBox的接口会更方便。
MyMessageBox.h

#ifndef MyMessageBox_H
#define MyMessageBox_H

#include <QApplication>
#include <QDebug>
#include <QDialog>
#include <QDialogButtonBox>
#include <QFile>
#include <QHBoxLayout>
#include <QIcon>
#include <QLabel>
#include <QMetaEnum>
#include <QPixmap>
#include <QPushButton>
#include <QVBoxLayout>

class MyMessageBox : public QDialog {
    Q_OBJECT

public:
    enum Icon {
        NoIcon = 0,
        Information = 1,
        Question = 2,
        Success = 3,
        Warning = 4,
        Critical = 5
    };
    Q_ENUM(Icon)  //使用Q_ENUM注册枚举

    enum StandardButton {
        //尽量保持与 QDialogButtonBox::StandardButton 一致,在创建按钮时可能会用到 & 运算
        NoButton = 0x00000000,
        Ok = 0x00000400,
        Save = 0x00000800,
        SaveAll = 0x00001000,
        Open = 0x00002000,
        Yes = 0x00004000,
        YesToAll = 0x00008000,
        No = 0x00010000,
        NoToAll = 0x00020000,
        Abort = 0x00040000,
        Retry = 0x00080000,
        Ignore = 0x00100000,
        Close = 0x00200000,
        Cancel = 0x00400000,
        Discard = 0x00800000,
        Help = 0x01000000,
        Apply = 0x02000000,
        Reset = 0x04000000,
        RestoreDefaults = 0x08000000,

        FirstButton = Ok,
        LastButton = RestoreDefaults
    };
    Q_ENUM(StandardButton)
    Q_DECLARE_FLAGS(StandardButtons, StandardButton)
    Q_FLAG(StandardButtons)

    enum ButtonRole {
        //保持与 QDialogButtonBox::ButtonRole 一致
        InvalidRole = -1,
        AcceptRole,
        RejectRole,
        DestructiveRole,
        ActionRole,
        HelpRole,
        YesRole,
        NoRole,
        ResetRole,
        ApplyRole,

        NRoles
    };

    explicit MyMessageBox(QWidget* parent = nullptr);
    MyMessageBox(Icon icon, const QString& title, const QString& text, StandardButtons buttons,
                 QWidget* parent = nullptr);  //构造函数有默认值的要放后面
    ~MyMessageBox();

    void setTitle(const QString& title);

    Icon icon() const;
    void setIcon(Icon icon);

    QPixmap iconPixmap() const;
    void setIconPixmap(const QPixmap& pixmap);

    QString text() const;
    void setText(const QString& text);

    StandardButtons standardButtons() const;
    void setStandardButtons(StandardButtons buttons);
    StandardButton standardButton(QAbstractButton* button) const;
    QAbstractButton* button(StandardButton which) const;

    ButtonRole buttonRole(QAbstractButton* button) const;

    QAbstractButton* clickedButton() const;

    static StandardButton information(QWidget* parent, const QString& text, QString title = "Message", StandardButtons buttons = Ok);
    static StandardButton question(QWidget* parent, const QString& text, QString title = "Message", StandardButtons buttons = StandardButtons(Yes | No));
    static StandardButton success(QWidget* parent, const QString& text, QString title = "Message", StandardButtons buttons = Ok);
    static StandardButton warning(QWidget* parent, const QString& text, QString title = "Message", StandardButtons buttons = Ok);
    static StandardButton critical(QWidget* parent, const QString& text, QString title = "Message", StandardButtons buttons = Ok);

    static StandardButton showMessageBox(QWidget* parent, Icon icon, const QString& text, QString title, StandardButtons buttons);
    static void setMessageBoxGeometry(QWidget* parent, MyMessageBox& msgBox);

private slots:
    void slotPushButtonClicked(QAbstractButton* button);

private:
    void init();
    void setupLayout();
    QPixmap standardIcon(Icon icon);
    void setClickedButton(QAbstractButton* button);
    void finalize(QAbstractButton* button);
    int dialogCodeForButton(QAbstractButton* button) const;
    void setPushButtonProperty(QList<QAbstractButton*> buttonList);

private:
    QLabel* m_pIconLabel;
    MyMessageBox::Icon m_icon;
    QLabel* m_pTextLabel;
    QLabel* m_pLineLabel;
    QDialogButtonBox* m_pButtonBox;
    QAbstractButton* m_pClickedButton;
};

//在全局任意地方使用"|"操作符计算自定义的枚举量,需要使用Q_DECLARE_OPERATORS_FOR_FLAGS宏
Q_DECLARE_OPERATORS_FOR_FLAGS(MyMessageBox::StandardButtons)

#endif  // MyMessageBox_H

};

//在全局任意地方使用"|"操作符计算自定义的枚举量,需要使用Q_DECLARE_OPERATORS_FOR_FLAGS宏
Q_DECLARE_OPERATORS_FOR_FLAGS(MyMessageBox::StandardButtons)

#endif  // MyMessageBox_H

MyMessageBox.cpp

#include "MyMessageBox.h"

#define MESSAGEWIDTH 450  //界面的大小
#define MESSAGEHEIGHT 225

#define TEXTFONTFAMILY "微软雅黑"  //text的字体样式和大小
#define TEXTFONTSIZE 12

#define BUTTONFONTFAMILY "微软雅黑"  //按钮的字体样式和大小
#define BUTTONFONTSIZE 10

#define BUTTONWIDTH 100  //按钮的大小
#define BUTTONHEIGHT 30

MyMessageBox::MyMessageBox(QWidget* parent) :
    QDialog(parent) {
    init();
}

MyMessageBox::MyMessageBox(Icon icon, const QString& title, const QString& text, StandardButtons buttons, QWidget* parent) :
    QDialog(parent) {
    init();
    setTitle(title);
    setIcon(icon);
    setText(text);
    if (buttons != NoButton)
        setStandardButtons(buttons);
}

MyMessageBox::~MyMessageBox() {}

void MyMessageBox::setTitle(const QString& title) {
    setWindowTitle(title);
}

MyMessageBox::Icon MyMessageBox::icon() const {
    return m_icon;
}

void MyMessageBox::setIcon(MyMessageBox::Icon icon) {
    setIconPixmap(standardIcon(icon));
    m_icon = icon;
}

QPixmap MyMessageBox::iconPixmap() const {
    return *m_pIconLabel->pixmap();
}

void MyMessageBox::setIconPixmap(const QPixmap& pixmap) {
    //    m_pIconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    m_pIconLabel->setPixmap(pixmap);
    m_icon = NoIcon;
}

QString MyMessageBox::text() const {
    return m_pTextLabel->text();
}

void MyMessageBox::setText(const QString& text) {
    m_pTextLabel->setFont(QFont(TEXTFONTFAMILY, TEXTFONTSIZE));
    m_pTextLabel->setText(text);
}

MyMessageBox::StandardButtons MyMessageBox::standardButtons() const {
    QDialogButtonBox::StandardButtons standardButtons = m_pButtonBox->standardButtons();
    return MyMessageBox::StandardButtons(int(standardButtons));  //不同类型的枚举转换
}

void MyMessageBox::setStandardButtons(StandardButtons buttons) {
    QDialogButtonBox::StandardButtons standardButtons = QDialogButtonBox::StandardButtons(int(buttons));
    m_pButtonBox->setStandardButtons(standardButtons);
    //    m_pButtonBox->setStandardButtons(QDialogButtonBox::StandardButtons(int(buttons)));  //上面两句归为一句
    setPushButtonProperty(m_pButtonBox->buttons());
}

MyMessageBox::StandardButton MyMessageBox::standardButton(QAbstractButton* button) const {
    QDialogButtonBox::StandardButton standardButton = m_pButtonBox->standardButton(button);
    return (MyMessageBox::StandardButton)standardButton;  //转化为当前类的StandardButton类型
}

QAbstractButton* MyMessageBox::button(MyMessageBox::StandardButton which) const {
    QDialogButtonBox::StandardButton standardButton = QDialogButtonBox::StandardButton(which);
    return m_pButtonBox->button(standardButton);
}

MyMessageBox::ButtonRole MyMessageBox::buttonRole(QAbstractButton* button) const {
    QDialogButtonBox::ButtonRole buttonRole = m_pButtonBox->buttonRole(button);
    return MyMessageBox::ButtonRole(buttonRole);
}

QAbstractButton* MyMessageBox::clickedButton() const {
    return m_pClickedButton;
}

MyMessageBox::StandardButton MyMessageBox::information(QWidget* parent, const QString& text, QString title, StandardButtons buttons) {
    return showMessageBox(parent, Information, text, title, buttons);
}

MyMessageBox::StandardButton MyMessageBox::question(QWidget* parent, const QString& text, QString title, StandardButtons buttons) {
    return showMessageBox(parent, Question, text, title, buttons);
}

MyMessageBox::StandardButton MyMessageBox::success(QWidget* parent, const QString& text, QString title, StandardButtons buttons) {
    return showMessageBox(parent, Success, text, title, buttons);
}

MyMessageBox::StandardButton MyMessageBox::warning(QWidget* parent, const QString& text, QString title, StandardButtons buttons) {
    return showMessageBox(parent, Warning, text, title, buttons);
}

MyMessageBox::StandardButton MyMessageBox::critical(QWidget* parent, const QString& text, QString title, StandardButtons buttons) {
    return showMessageBox(parent, Critical, text, title, buttons);
}

MyMessageBox::StandardButton MyMessageBox::showMessageBox(QWidget* parent, Icon icon, const QString& text, QString title, StandardButtons buttons) {
    MyMessageBox msgBox(icon, title, text, buttons, parent);
    //静态函数只能调用静态函数,setMessageBoxGeometry()必须声明为静态函数
    setMessageBoxGeometry(parent, msgBox);
    if (msgBox.exec() == -1)
        return MyMessageBox::Cancel;
    return msgBox.standardButton(msgBox.clickedButton());
}

void MyMessageBox::setMessageBoxGeometry(QWidget* parent, MyMessageBox& msgBox) {
    QRect rect = parent->geometry();
    int x = rect.x() + (rect.width() - msgBox.geometry().width()) / 2;
    int y = rect.y() + (rect.height() - msgBox.geometry().height()) / 2;
    msgBox.setGeometry(x, y, msgBox.geometry().width(), msgBox.geometry().height());
    msgBox.move(x, y);
}

void MyMessageBox::slotPushButtonClicked(QAbstractButton* button) {
    setClickedButton(button);
    finalize(button);
    close();
}

void MyMessageBox::init() {
    resize(QSize(MESSAGEWIDTH, MESSAGEHEIGHT));
    setWindowIcon(QIcon(":/new/prefix1/Icon/project.ico"));
    setWindowTitle("Message");
    //对于继承的QDialog,其Flags必须包含Qt::Dialog,不能自定义CustomizeWindowHint
    //否则在构造中指定了parent之后会出现:标题栏消失以及窗口不在正中间
    //setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);  //设置右上角按钮
    Qt::WindowFlags flags = Qt::Dialog;
    flags |= Qt::WindowCloseButtonHint;
    setWindowFlags(flags);  //去掉标题栏右上角的问号
    //setAttribute(Qt::WA_DeleteOnClose);                                   //关闭窗口时将窗口释放掉即释放内存

    m_pIconLabel = new QLabel(this);
    m_pIconLabel->setObjectName(QLatin1String("iconLabel"));
    m_pIconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);  //图标不可拉伸和缩小,固定大小
    m_pTextLabel = new QLabel(this);
    m_pTextLabel->setObjectName(QLatin1String("textLabel"));
    m_pTextLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);  //label中的内容可用鼠标选择文本复制,链接激活
    m_pTextLabel->setOpenExternalLinks(true);                           //label中的内容若为链接,可直接点击打开
    m_pLineLabel = new QLabel(this);
    m_pLineLabel->setFrameStyle(QFrame::HLine | QFrame::Sunken);  //Sunken:凹陷,Raised:凸起
    m_pButtonBox = new QDialogButtonBox(this);                    //默认按钮为水平布局Qt::Horizontal
    m_pButtonBox->setObjectName(QLatin1String("buttonBox"));
    connect(m_pButtonBox, &QDialogButtonBox::clicked, this, &MyMessageBox::slotPushButtonClicked);

    setupLayout();

    setModal(true);

    setStyleSheet("QDialog{background-color:rgb(255 , 255 , 255);}"
                  "QPushButton{background-color:#E0E0E0;border: 1px solid #A6A6A6;border-radius:5px;}"
                  "QPushButton:hover{color:white;background-color:#4188FF;border-radius:5px;border: 0px}"
                  //                  "QPushButton{background-color:#E0E0E0;border: 1px solid #C2C2C2;border-radius:5px;}"
                  //                  "QPushButton:hover{background-color:#C2C2C2;border-radius:5px;border: 0px}"
                  "QPushButton:pressed{padding-left:3px;padding-top:3px;}");
}

void MyMessageBox::setupLayout() {
    QHBoxLayout* HLay = new QHBoxLayout;
    HLay->addWidget(m_pIconLabel, 1, Qt::AlignVCenter | Qt::AlignRight);
    HLay->addWidget(m_pTextLabel, 5, Qt::AlignCenter);
    QHBoxLayout* HLay1 = new QHBoxLayout;
    HLay1->addWidget(m_pButtonBox, Qt::AlignRight);
    //    QMargins margin;
    //    margin.setRight(9);
    //    HLay1->setContentsMargins(margin);  //调节按钮不要太靠右
    QVBoxLayout* VLay = new QVBoxLayout;
    VLay->addLayout(HLay, 10);
    VLay->addWidget(m_pLineLabel, 1);
    VLay->addLayout(HLay1, 4);
    VLay->setSpacing(0);

    setLayout(VLay);
}

QPixmap MyMessageBox::standardIcon(Icon icon) {
    QPixmap pixmap;
    switch (icon) {
        case MyMessageBox::Information:
            pixmap.load(":/new/prefix1/Image/Information.png");
            break;
        case MyMessageBox::Question:
            pixmap.load(":/new/prefix1/Image/Question.png");
            break;
        case MyMessageBox::Success:
            pixmap.load(":/new/prefix1/Image/Success.png");
            break;
        case MyMessageBox::Warning:
            pixmap.load(":/new/prefix1/Image/Warning.png");
            break;
        case MyMessageBox::Critical:
            pixmap.load(":/new/prefix1/Image/Critical.png");
            break;
        default:
            break;
    }
    if (!pixmap.isNull())
        return pixmap;
    return QPixmap();
}

void MyMessageBox::setClickedButton(QAbstractButton* button) {
    m_pClickedButton = button;
}

void MyMessageBox::finalize(QAbstractButton* button) {
    int dialogCode = dialogCodeForButton(button);
    if (dialogCode == QDialog::Accepted) {
        emit accept();
    } else if (dialogCode == QDialog::Rejected) {
        emit reject();
    }
}

int MyMessageBox::dialogCodeForButton(QAbstractButton* button) const {
    switch (buttonRole(button)) {
        case MyMessageBox::AcceptRole:
        case MyMessageBox::YesRole:
            return QDialog::Accepted;
        case MyMessageBox::RejectRole:
        case MyMessageBox::NoRole:
            return QDialog::Rejected;
        default:
            return -1;
    }
}

void MyMessageBox::setPushButtonProperty(QList<QAbstractButton*> buttonList) {
    for (int i = 0; i < buttonList.size(); i++) {
        QPushButton* pushButton = qobject_cast<QPushButton*>(buttonList.at(i));
        pushButton->setMinimumSize(BUTTONWIDTH, BUTTONHEIGHT);
        pushButton->setFont(QFont(BUTTONFONTFAMILY, BUTTONFONTSIZE));
    }
}

注意:需要在Resources文件中自己手动添加icon图片。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【QT】如何自定义QMessageBox的窗口大小,通过继承QDialog重新实现美观的弹窗 的相关文章

  • Android 版 Qt 和 BoringSSL

    我正在开发一个基于 Qt 的 Android 应用程序 它使用 QSslSocket 下载数据 由于 Android 从 OpenSSL 转向 BoringSSL 因为依赖 OpenSSL 库的 Marshmallow Qt 程序在 And
  • 无法将 [未定义] 分配给 QColor

    我正在使用 Qt 5 11 构建 运行代码 代码中有QML风格如下 Button style delegate Component id enabledButtonStyle ButtonStyle padding top 0 paddin
  • 在 Windows 上以 QML 播放 RTSP 视频

    我正在尝试将 QML 中的 RTSP 流播放到视频标签中 如下所示 Repeater model 8 Video Layout fillWidth true Layout fillHeight true fillMode VideoOutp
  • MSVC C4100:“应用程序”:未引用的形式参数警告

    使用 MSVC 编译时 以下代码会生成 C4100 警告 这怎么可能 显然引用了 应用程序 class ApplicationInfo public QObject Q OBJECT public static void initializ
  • 运行最新版本时没有“最新”消息?

    我正在尝试使用Sparkle https sparkle project org与 Qt Go 的绑定 https github com therecipe qt app 闪光 m import
  • 在 QtCreator 中调试时如何查看 qDebug 消息

    我正在从 Eclipse CDT 带有 Qt 集成插件 过渡到 QtCreator 2 0 但仍有一件事困扰着我 QtCreator 当我在 QtCreator 中调试时 我在Application output tab直到我停止正在调试的
  • 如何使用bind将成员函数作为函数指针传递?

    我试图将成员函数作为函数指针传递 这样我就不需要依赖单例或全局函数来处理 Qt 5 中的 Qt 消息 据我所知 我的 std function 是正确的类型 它具有正确的签名 并且绑定应该允许我插入隐式this指针 本质上是将成员函数传递为
  • qvariant 作为 qhash 中的键

    我想创建一个带有 QVariants 键的数据结构 它看起来像这样 QHash
  • Qt 和 MOC 的困境与简单的制作

    我想这更像是一个 GNU Make 问题 而不是 Qt 和 moc 但这里是 我有一个包含多个目录Q OBJECTS 我有一些简单的代码 它收集所有这些 例如 MOCS shell grep l Q OBJECT HEADERS Assum
  • 如何通过信号和槽传递参数?

    我的 GUI 包括LineEdit and a 按钮 当 的时候按钮单击后 插槽clicked 叫做 我想在之间建立信号槽关系clicked 作为信号和doSomething 作为插槽 问题是doSomething 无权访问 UI 并且do
  • PyQt:如何通过匿名代理使用网页

    这真让我抓狂 我想在 QWebPage 中显示一个 url 但我想通过匿名代理来实现 Code setting up the proxy proxy QNetworkProxy proxy setHostName 189 75 98 199
  • 使用 QTestLib 时抑制 qDebug

    我正在向 Qt 中的项目添加单元测试 并希望使用 QTestLib 我已经设置了测试并且它们运行良好 问题是在项目中我们重写了 qDebug 以输出到我们自己的日志文件 这在运行应用程序时效果很好 问题是当我测试类时 它有时会开始记录 然后
  • QWebView等待加载

    bool MainWindow waitForLoad QWebView view QEventLoop loopLoad QTimer timer QObject connect view SIGNAL loadFinished bool
  • 使用 QPrinter 打印第 x 页(共 y 页)

    我使用 qt 从 html 代码生成 pdf 文件 QTextDocument document new QTextDocument document gt setHtml htmlContent QPrinter printer QPri
  • 如何阻止 Qt Creator 将可执行文件放置在“调试”子目录中?

    我正在 Qt Creator 中构建一个项目 虽然我不关心中间 obj 文件去哪里 但重要的是最终的可执行文件应放入 并运行 许多依赖项 DLL 等所在的特定目录中 被发现 因此 在 Qt Creator 中 我选择 Shadow Buil
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 在 Qt 中旋转图像

    在我的应用程序中 我想旋转图像 我已将图像设置为QLabel 我已经设置了一个QPushButton 单击该按钮时我想向四个方向旋转图像 右 gt 底部 gt 左 gt 顶部 有什么帮助吗 假设您有一个指向 QLabel 的指针 您可以执行
  • QStandardItemModel::removeRows() 在我的用例中不起作用

    基本上我想删除模型中的所有行 我更喜欢使用removeRows 代替clear 因为我想保留我的标题 我想我错过了一些东西 文档在这里 http doc qt nokia com 4 7 snapshot qstandarditemmode
  • QPainter 性能高帧率

    我试图在 QPainter 中以 60fps 的速度显示视频 在 OpenGLwidget 中 我遇到一个问题 有时绘图花费的时间太长 并且在使用 QPainter 时发生下一个重绘事件 这会生成警告和随机崩溃 有几个问题 是否有一种 Qt
  • 无法在 QGLWidget 中设置所需的 OpenGL 版本

    我正在尝试在 Qt 4 8 2 中使用 QGLWidget 我注意到 QGLWidget 创建的默认上下文不显示 OpenGL 3 1 以上的任何输出 Qt wiki 有一个教程 http qt project org wiki How t

随机推荐

  • 2014 奇虎360 笔试主观题

    1 在审计某一开源项目的代码时 假设有下面一个foo 子函数的实现 从安全的角度看 会存在安全漏洞吗 有的话 请 1 描述漏洞细节 2 说明可以利用的方法 3 还有该怎么修补漏洞 没有的话 也请说明为什么 int foo void func
  • QT.setStyleSheet()用法

    1 基本用法 textViewer gt setStyleSheet background color 00FF00 背景颜色 color FF0000 前景色 color rgb 255 0 0 color rgbd 255 0 0 0
  • selenium+java实现web自动化例子

    简单记录 有不正确的地方请指出 selenium java可以实现对web页面的自动化控制 在公司内部比较稳定 页面迭代较少的后台web系统使用时非常有效 web自动化收益最大化的情况 1 多更新于后端 前端页面迭代较少 2 在日常迭代中页
  • C++vector容器

    vector容器被称为动态数组 也被称为向量 它与array容器的区别是 array是静态数组 动态扩展 并不是在原空间之后续接新空间 而是找更大的内存空间 然后将原数据拷贝新空间 释放原空间 at 函数 返回对矢量中指定位置的元素的引用
  • 第零章 内核网络相关配置选项--基于Linux 3.10

    Kconfig选项 packet protocol 被直接和网络设备通信的应用程序使用 其没有使用内核的其它协议 像tcpdump支持需要使能该选项 af packet lt gt Packet socket 支持PF PACKET套接字
  • kubeadm构建(Calico+Dashboard+Containerd)

    文章目录 前言 一 环境 二 部署容器网络 CNI master操作 1 下载yamll 2 修改yaml 3 部署 三 部署 Dashboard 1 下载yaml 2 修改yaml 3 部署 4 创建管理员 四 切换容器引擎为Contai
  • 区块链开发之Solidity编程基础(一)

    Solidy是当前编写智能合约的主流语言 概要 sol文件结构 编译开发 引入其他文件 注释 代码注释 文档注释 合约 状态变量 类型 值类型 1 布尔类型 2 整型 3 地址 4 定长字节数组 5 有理数和整型字面量 6 枚举类型 7 函
  • controller与servlet的区别

    理解1 你可以理解为 Spring MVC是基于servlet的 它有一个DispatherServlet 然后它负责处理请求 并且调用了你的controller 打一个比方 web网站是应用程序么 你可以说浏览器是一个应用程序 而web网
  • ElementUi tab组件切换导致echarts宽度变窄问题

    解决tab组件变成100px的问题 使用echarts实例自带的resize 方法
  • 大话数据结构:栈与队列(1)

    栈 限定仅在表尾进行插入和删除操作的线性表 栈顶 允许插入和删除的一端 栈底 不允许插入和删除的一端 空栈 不含任何数据元素的栈 后进先出的线性表 LIFO结构 进栈 栈的插入 出栈 栈的删除 元素数量多 出栈的变化会更多 栈的抽象数据类型
  • pytorch实战-图像分类(一)(数据预处理)

    目录 1 导入各种库 2 数据预处理 2 1数据读取 2 2图像增强 3 构建数据网络 3 1网络构建 3 2读取标签对应的名字 4 展示数据 4 1数据转换 4 2画图 5 模型训练 1 导入各种库 上代码 import os impor
  • QQ IDKey生成--一键加群

    今天网站用到一个点击链接调用qq自动加群的弹窗功能 感觉还挺方面 记录下来以备后用 首先打开qq推广首页http shang qq com v3 index html 然后登陆需要绑定的QQ号 选择左侧一键加群组件 左侧 请选择你创建的群
  • cdc多bit信号-握手处理

    对于多bit数据跨时钟 各个bit之间路径延迟不一样 源时钟域给的数据是2 b11 目的时钟域采样到的数据可能2 b10 因此两级触发器对于单bit数据跨时钟是可以用的 但是对于多bit数据跨时钟就会出错 握手处理的关键是利用源的时钟req
  • ev3的c语言编程软件,乐高EV3编程软件教育版下载

    乐高EV3编程软件教育版官方版是一款用于机器人编程的应用工具 乐高EV3编程软件教育版最新版可以通过可视化图标形式编程 用以控制机器人的各种动作指令 乐高EV3编程软件教育版操作起来比较简单 发挥你的想象 创造无限的编程可能 软件说明 乐高
  • 【随笔三】一篇文章理清 节流、防抖以及应用场景

    前言 防抖 和 节流 很多人特别容易把概念混倄 今天 一篇文章教你彻底理清其中的概念及应用场景 先说共同点 防抖 和 节流 函数都是为了 限制函数的执行频次 从而优化函数触发频率过高导致的响应速度跟不上触发频率 导致出现延迟 卡顿的现象以及
  • css设置背景图片大小_如何使用CSS设置背景图片大小?

    css设置背景图片大小 Introduction 介绍 As we all know that the images are a very responsive yet very creative way to display your w
  • Python教程基础篇,超详细超长!

    安装Python 前往 官网下载 对应平台对应工具 另外Python2 7版本和3 3版本并不兼容 所以开发时请注意使用Python的版本 作为Mac OS X使用者 其实更推荐 PyCharm IDE 安装之后直接使用即可 数据类型 计算
  • 在多行文本输入框光标指定位置插入内容并改变光标位置

    h1 测试在指定位置插入内容并改变光标位置 h1
  • java反射<T extends Comparable<? super T>>说明

  • 【QT】如何自定义QMessageBox的窗口大小,通过继承QDialog重新实现美观的弹窗

    目录 1 QMessageBox原有的弹窗 2 网上第一种方法 通过样式表setStyleSheet实现改变弹窗大小 总体不美观 3 网上第二种方法 重写ShowEvent 改变弹窗大小 总体也不美观 4 最好的办法 继承QDialog重新