Qt 之 自定义提示信息框—迅雷风格

一、简述

最近一直在研究迅雷9的界面,花了点时间做了几个通用的提示信息框,整体风格与迅雷9界面相同。支持模态和非模态两种模式窗口。提示框效果见下图。

Qt 之 自定义提示信息框—迅雷风格_第1张图片

我们可以根据设置不同的参数来设置提示框标题、显示内容、显示图标、下方按钮个数,可以设置为输入框,也可以设置为模态/非模态对话框,实现了自定义的QMessageBox。目前实现了提示框基本功能,后续将继续拓展更多功能。小伙伴们可以根据需要自定义其他功能,下面直接上代码。

后续更改了一下样式,修改为QQ风格的提示窗口,详情见 Qt 之 自定义提示信息框—QQ风格 。

Qt 之 自定义提示信息框—迅雷风格_第2张图片

二、代码之路

看代码之前需要看一下Qt 之 自定义窗口标题栏这一篇文章,因为这里用到了这篇文章中写到的自定义标题栏。

如果需要了解如何实现窗口的模态与非模态对话框可以看一下 Qt 之 模态与非模态窗口的介绍及 实现QDialog的exec()方法 这一篇文章。

这里新建任务窗口类MyMessageBox 继承了BaseWindow类,所以省去了一些代码实现(主要包括顶部标题栏、鼠标按住标题栏进行拖动,窗口背景色等 ),有需要的小伙伴可以去看一下这一篇文章。

mymessagebox.h

#include 
#include "ui_mymessagebox.h"
#include "basewindow.h"

enum ChosseResult
{
    ID_OK = 0,                      // 确定;
    ID_CANCEL                       // 取消;
};

enum MessageType
{
    MESSAGE_INFORMATION = 0,        // 提示信息;
    MESSAGE_WARNNING,               // 提示警告;
    MESSAGE_QUESTION,               // 提示询问;
    MESSAGE_INPUT                   // 提示输入框;
};

enum MessageButtonType
{
    BUTTON_OK = 0,                  // 只有确定按钮;
    BUTTON_OK_AND_CANCEL,           // 确定、取消按钮;
    BUTTON_CLOSE                    // 关闭按钮;
};

class MyMessageBox : public BaseWindow
{
    Q_OBJECT

public:
    MyMessageBox(QWidget *parent = 0);
    ~MyMessageBox();

    void setWindowTitle(QString title, int titleFontSize = 10);
    void setContentText(QString contentText);
    void setMessageType(MessageType messageType);
    void setButtonType(MessageButtonType buttonType);
    void setMessageContent(QString messageContent);

public:
    int static showMyMessageBox(QWidget* parent, const QString &title,const QString &contentText , MessageType messageType, MessageButtonType messageButtonType , bool isModelWindow = false);


private:
    void initWindow();
    void initTitleBar();
    int exec();

    void paintEvent(QPaintEvent *event);
    void closeEvent(QCloseEvent *event);

private slots:
    void onOkClicked();
    void onCancelClicked();

private:
    Ui::MyMessageBox ui;
    QEventLoop* m_eventLoop;
    ChosseResult m_chooseResult;
};

mymessagebox.cpp

#include "mymessagebox.h"
#include 
#include 

MyMessageBox::MyMessageBox(QWidget *parent)
    : BaseWindow(parent)
    , m_eventLoop(NULL)
    , m_chooseResult(ID_CANCEL)
{
    ui.setupUi(this);
    initWindow();
}

MyMessageBox::~MyMessageBox()
{

}

void MyMessageBox::initWindow()
{
    initTitleBar();
    loadStyleSheet("MyMessageBox/MyMessageBox");
    Qt::WindowFlags flags = this->windowFlags();
    this->setWindowFlags(flags | Qt::Window);

    ui.inputContent->setVisible(false);

    connect(ui.pButtonOk, SIGNAL(clicked()), this, SLOT(onOkClicked()));
    connect(ui.pButtonCancel, SIGNAL(clicked()), this, SLOT(onCancelClicked()));
}

// 初始化标题栏;
void MyMessageBox::initTitleBar()
{
    m_titleBar->move(1, 2);
    m_titleBar->setWindowBorderWidth(2);
    m_titleBar->setBackgroundColor(255, 255, 255);
    m_titleBar->setButtonType(ONLY_CLOSE_BUTTON);
    m_titleBar->setTitleWidth(this->width());
}

void MyMessageBox::paintEvent(QPaintEvent *event)
{
    // 绘制窗口白色背景色;
    QPainter painter(this);
    QPainterPath pathBack;
    pathBack.setFillRule(Qt::WindingFill);
    pathBack.addRect(QRect(0, 0, this->width(), this->height()));
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
    painter.fillPath(pathBack, QBrush(QColor(255, 255, 255)));

    // 绘制按钮部分灰色背景;
    QPainterPath pathButtonBack;
    pathButtonBack.setFillRule(Qt::WindingFill);
    pathButtonBack.addRect(QRect(0, 110, this->width(), 48));
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
    painter.fillPath(pathButtonBack, QBrush(QColor(247, 247, 247)));

    // 绘制窗口灰色边框;
    QPen pen(QColor(204, 204, 204));
    painter.setPen(pen);
    painter.drawRect(0, 0, this->width() - 1, this->height() - 1);

    // 绘制窗口上方蓝条;
    QPainterPath pathHead;
    pathHead.setFillRule(Qt::WindingFill);
    pathHead.addRect(QRect(0, 0, this->width(), 2));
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
    painter.fillPath(pathHead, QBrush(QColor(15, 151, 255)));

    return QWidget::paintEvent(event);
}

void MyMessageBox::setWindowTitle(QString title , int titleFontSize)
{
    m_titleBar->setTitleContent(title, titleFontSize);
}

void MyMessageBox::setContentText(QString contentText)
{
    ui.MessageContent->setText(contentText);
}

void MyMessageBox::setMessageType(MessageType messageType)
{
    switch (messageType)
    {
    case MESSAGE_INFORMATION:
        ui.MessageIcon->setPixmap(QPixmap(":/Resources/MyMessageBox/information.png"));
        break;
    case MESSAGE_WARNNING:
        ui.MessageIcon->setPixmap(QPixmap(":/Resources/MyMessageBox/warnning.png"));
        break;
    case MESSAGE_QUESTION:
        ui.MessageIcon->setPixmap(QPixmap(":/Resources/MyMessageBox/question.png"));
        break;
    case MESSAGE_INPUT:
        ui.MessageIcon->setVisible(false);
        ui.inputContent->setVisible(true);
    default:
        break;
    }
}

void MyMessageBox::setButtonType(MessageButtonType buttonType)
{
    switch (buttonType)
    {
    case BUTTON_OK:
    {
        ui.pButtonOk->setText(QStringLiteral("确定"));
        ui.pButtonCancel->setVisible(false);
    }
        break;
    case BUTTON_OK_AND_CANCEL:
    {
        ui.pButtonOk->setText(QStringLiteral("确定"));
        ui.pButtonCancel->setText(QStringLiteral("取消"));
    }
        break;
    default:
        break;
    }
}

void MyMessageBox::setMessageContent(QString messageContent)
{
    ui.MessageContent->setText(messageContent);
}

// 显示提示框
// isModelWindow 参数设置提示框是否是模态
int MyMessageBox::showMyMessageBox(QWidget* parent, const QString &title, const QString &contentText, MessageType messageType, MessageButtonType messageButtonType, bool isModelWindow)
{
    MyMessageBox * myMessageBox = new MyMessageBox(parent);
    myMessageBox->setWindowTitle(title);
    myMessageBox->setContentText(contentText);
    myMessageBox->setMessageType(messageType);
    myMessageBox->setButtonType(messageButtonType);
    if (isModelWindow)
    {
        // 设置为模态窗口时,参数parent必须设置父窗口指针,否则模态设置无效;
        // 因为 Qt::WindowModal 参数只对父窗口有效,如果想要模态对全局窗口都有效可以设置 Qt::ApplicationModal
        return myMessageBox->exec();
    }
    else
    {
        myMessageBox->show();
    }

    return 0;
}

int MyMessageBox::exec()
{
    // 因为QWidget没有exec()方法,所以需要自己定义来完成exec()方法;
    // 而exec()方法就是直接设置窗口显示为模态,并且窗口关闭结束后返回用户选择结果(按了确定还是取消按钮);
    // 而show()方法只是显示窗口,并不会设置窗口的模态或者非模态,需要自己调用setWindowModality()方法进行设置;
    // 而且show()方法并不会返回用户选择结果;
    // 这里也可以继承QDialog类,QDialog有自己的exec()方法,根据返回 Accepted, Rejected来决定是否按了确定按钮;

    // 设置为窗口级模态,也可设置为应用程序及模态 Qt::ApplicationModal;
    this->setWindowModality(Qt::WindowModal); 
    show();
    // 使用事件循环QEventLoop ,不让exec()方法结束,在用户选择确定或者取消后,关闭窗口结束事件循环,并返回最后用户选择的结果;
    // 根据返回结果得到用户按下了确定还是取消,采取相应的操作。从而模拟出QDialog类的exec()方法;
    m_eventLoop = new QEventLoop(this);
    m_eventLoop->exec();

    return m_chooseResult;
}

void MyMessageBox::onOkClicked()
{
    m_chooseResult = ID_OK;
    close();
}

void MyMessageBox::onCancelClicked()
{
    m_chooseResult = ID_CANCEL;
    close();
}

void MyMessageBox::closeEvent(QCloseEvent *event)
{
    // 关闭窗口时结束事件循环,在exec()方法中返回选择结果;
    if (m_eventLoop != NULL)
    {
        m_eventLoop->exit();
    }
    event->accept();
}

样式

*{font-family:Microsoft YaHei;}

QLabel#MessageContent
{
    font-size:14px;
}

QPushButton#pButtonOk
{
    color:white;
    background-color:rgb(14 , 150 , 254);
    border: 1px solid rgb(11 , 137 , 234);
}

QPushButton#pButtonOk:hover
{
    color:white;
    background-color:rgb(44 , 137 , 255);
    border: 1px solid rgb(11 , 137 , 234);
}

QPushButton#pButtonOk:pressed
{
    color:white;
    background-color:rgb(14 , 135 , 228);
    border: 1px solid rgb(12 , 138 , 235);
    padding-left:3px;
    padding-top:3px;
}

QPushButton#pButtonCancel
{
    color:black;
    background-color:rgb(238 , 238 , 238);
    border: 1px solid rgb(183 , 183 , 183);
}

QPushButton#pButtonCancel:hover
{
    color:black;
    background-color:rgb(228 , 240 , 250);
    border: 1px solid rgb(15 , 150 , 255);
}

QPushButton#pButtonCancel:pressed
{
    color:black;
    background-color:rgb(204 , 228 , 247);
    border: 1px solid rgb(1 , 84 , 153);
    padding-left:3px;
    padding-top:3px;
}

QLineEdit#inputContent
{
    border: 1px solid rgb(195 , 195 , 195);
}

QLineEdit#inputContent:hover
{
    border: 1px solid rgb(1 , 186 , 255 );
}

测试代码

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyMessageBox::showMyMessageBox(NULL, QStringLiteral("删除"), QStringLiteral("您确定要删除此任务吗?"), MESSAGE_WARNNING, BUTTON_OK_AND_CANCEL);

    MyMessageBox::showMyMessageBox(NULL, QStringLiteral("退出"), QStringLiteral("任务为下载完,确定退出吗?"), MESSAGE_QUESTION, BUTTON_OK_AND_CANCEL);

    MyMessageBox::showMyMessageBox(NULL, QStringLiteral("提示"), QStringLiteral("您输入的用户名不正确"), MESSAGE_INFORMATION, BUTTON_OK_AND_CANCEL);

    MyMessageBox::showMyMessageBox(NULL, QStringLiteral("重命名"), QStringLiteral("文件名: "), MESSAGE_INPUT, BUTTON_OK_AND_CANCEL);
    return a.exec();
}

界面设计

Qt 之 自定义提示信息框—迅雷风格_第3张图片


运行结果图:

Qt 之 自定义提示信息框—迅雷风格_第4张图片

Qt 之 自定义提示信息框—迅雷风格_第5张图片

Qt 之 自定义提示信息框—迅雷风格_第6张图片

Qt 之 自定义提示信息框—迅雷风格_第7张图片

模态窗口测试效果

Qt 之 自定义提示信息框—迅雷风格_第8张图片


代码其实很简单,这里只是实现了基本功能(根据参数设置不同样式的提示框),更多可以参考Qt的QMessageBox,在后续会增加更多功能实现,敬请期待哈 O(∩_∩)O !


更多文章

Qt 之 自定义提示信息框—QQ风格

Qt 之 模态与非模态窗口的介绍及 实现QDialog的exec()方法

Qt 之 自定义窗口标题栏

代码下载

Qt 之 自定义提示信息框—QQ、迅雷风格 (包含了QQ和迅雷两种风格的提示框)

你可能感兴趣的:(Qt,qt,提示框,消息框,MessageBox,迅雷)