QT 写一个属于自己的消息弹窗MessageBox

前言
在接触公司的一个桌面应用项目后,发现里面很多窗体都是自己写的而不是使用QT自带的,例如消息弹窗。今天这篇博客就记录下来如何自己写一个消息弹窗。

内容可能有点多,但都是本人自己一步一步操作后,测试可行后才记录下博客这里来的,希望对看到这篇博客的朋友有所帮助!

由于我是在centos7使用QT编写的代码,操作步骤或者界面什么的可能与Window使用QT会有些不一样,但是都是类似的。

下面是一部分运行截图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我写的整个项目,将上传 csdn 和 百度网盘 后,放在下面 总结 处,需要的朋友自提!
项目所用到的资源文件也一起上传。



一、创建消息窗体

首先得有一个主窗体,自己先手动创建一个QT项目,创建后如下:
在这里插入图片描述

然后根据下图指引,在创建一个子窗体,用做消息弹窗:

  1. 右键选择Add New…
    在这里插入图片描述

  2. 选择Qt设计师界面类
    在这里插入图片描述

  3. 选择Widget
    在这里插入图片描述

  4. 可以适当修改一下名字
    在这里插入图片描述

  5. 到此,窗体就创建好了
    在这里插入图片描述

  6. 添加资源文件
    将资源文件夹msgbox放到项目路径下
    在这里插入图片描述
    1). 右键选择Add New…
    在这里插入图片描述
    2). 选择Qt Resource File
    在这里插入图片描述
    3). 可以设当修改名字
    在这里插入图片描述
    4). 再出现的页面中,下面点击 添加 - 添加前缀
    在这里插入图片描述
    5). 此时前缀这里会出现一些字符串,删掉剩下一个反斜杠即可
    在这里插入图片描述
    6). 点击 添加 - 添加文件
    在这里插入图片描述
    7). 再出现的弹窗中全选文件,点击右上角Open添加进来
    在这里插入图片描述

    8). 添加进来是这样着的,记得 Ctrl + s 保存一下
    在这里插入图片描述

到了这样,说明资源文件已经添加进来了!

也可以添加自己喜欢的图片、资源进来设置!


二、设置消息弹窗

  1. 双击MessageBox.ui进入设计师界面,将宽度设置为400,高度设置为150.

  2. 窗体设置样式
    右键对象,选择改变样式表…
    将样式设置为:

    background:rgb(255,255,255);
    border:1px solid rgba(110, 123, 146, 1);
    

在这里插入图片描述

  1. 拖动两个Widget
    托两个Widget到窗体上:
    1). 第一个widget设置宽度400,高度30,x为0,y为0;修改对象名为:widget_1
    2). 第二个widget设置宽度400,高度120,x为0,y为30;修改对象名为:widget_2
    在这里插入图片描述

  2. 给两个Widget添加标签和按钮

    1). widget_1
    设置widget_1样式为:
    background-image: url(:/msgbox/title_bg.png);

    拖一个Label:设置宽度90,高度20,x为10,y为5;修改对象名为:label_title;文本修改为:提示
    设置label_title样式为:
    border:0;color: rgb(255, 255, 255); background:transparent;

    拖一个PushButton:设置宽度18,高度18,x为375,y为6;修改对象名为:btn_close;删掉文本
    设置btn_close样式为:
    border:0px; background:transparent; background-image: url(:/msgbox/close_normal.png);

    2). widget_2
    设置widget_2样式为:
    background:transparent; background-color: rgb(255, 255, 255);

    拖一个Label:设置宽度32,高度32,x为40,y为30;修改对象名为:label_icon;删掉文本
    设置label_icon样式为:
    border:0; background:transparent; background-image: url(:/msgbox/tips_icon.png);

    拖一个Label:设置宽度291,高度41,x为80,y为30;修改对象名为:label_tips;文本可随意设置
    设置label_tips样式为:
    border:0; background:transparent; color: rgb(51, 51, 51);

    拖一个PushButton:设置宽度70,高度30,x为200,y为80;修改对象名为:btn_confirm;文本修改为:是
    设置btn_confirm样式为:
    border:0; background:transparent; background-image: url(:/msgbox/confirm_normal.png);

    拖一个PushButton:设置宽度70,高度30,x为290,y为80;修改对象名为:btn_cancel;文本修改为:否
    设置btn_cancel样式为:
    border:0; background:transparent; background-image: url(:/msgbox/cancel_normal.png);

    根据上面设置完成后,效果如下:
    在这里插入图片描述
    注意自己添加资源文件的路径,路径不对,是无法设置图片的!

具体坐标,大小,可以自己根据具体情况而设置!


三、编写代码

严格按照步骤完成上面的操作后,下面我们可以开始写代码了。

  1. 首先在MessageBox.h文件中添加两个结构体:

    // 设在按钮个数
    enum MSG_TYPE
    {
    	SA_OK           = 0,    // 只有一个“确定”按钮,且两秒钟后自动关闭消息窗口
    	SA_OKCANCEL     = 1,    // 一个“是”按钮,一个“否”按钮
    	SA_OKS          = 2     // 只有一个“确定”按钮,不会自动关闭消息窗口
    };
    
    // 设在提示的类型
    enum MSG_TIP_TYPE
    {
    	SA_SUCCESS      = 0,    // 完成
    	SA_FAILED       = 1,    // 错误
    	SA_WARNING      = 2,    // 警告
    	SA_TIPS         = 3,    // 提示
    	SA_QUESTION     = 4     // 未知
    };
    
  2. 添加头文件 #include < QDialog >
    并将MessageBox的基础修改为 class MessageBox : public QDialog { };

    在构造函数中添加两个参数:

    MessageBox(QWidget *parent = nullptr, MSG_TYPE nType = SA_OKCANCEL, MSG_TIP_TYPE nTipType = SA_TIPS);
    

    定义两个私有成员变量,用于接收构造函数传过来的两个参数:

    private:
    	int m_nType;
    	int m_nTipType;
    

    实现构造函数:

    MessageBox::MessageBox(QWidget *parent, MSG_TYPE nType, MSG_TIP_TYPE nTipType) :
    	QDialog(parent),
    	ui(new Ui::MessageBox)
    {
    	ui->setupUi(this);
    
    	m_nType = nType;
    	m_nTipType = nTipType;
    
    	setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    	// 设置窗体关闭时自动释放内存
    	this->setAttribute(Qt::WA_DeleteOnClose);
    
    
    	// 设在按钮
    	if(MSG_TYPE::SA_OK == m_nType)
    	{
        	ui->btn_cancel->setVisible(false);  // 隐藏“否”按钮
        	ui->btn_confirm->setText("确定");
    	}
    	else if(MSG_TYPE::SA_OKCANCEL == m_nType)
    	{
        	ui->btn_cancel->setVisible(true);   // 显示“否”按钮
        	ui->btn_confirm->setText("是");
    	}
    	else if (MSG_TYPE::SA_OKS == m_nType)
    	{
        	ui->btn_cancel->setVisible(false);  // 隐藏“否”按钮
        	ui->btn_confirm->setText("确定");
    	}
    
    	// 设在两个按钮样式,这样设在效果:当鼠标移动到按钮上方,会切换对应设在的图片,移开后又会设在回来
    	QString strStyle = "QPushButton{border:0;background:transparent;background-image: url(:/msgbox/cancel_normal.png);}"
                       "QPushButton:hover{border:0;background:transparent;background-image: url(:/msgbox/cancel_hover.png);}";
    	ui->btn_cancel->setStyleSheet(strStyle);
    
    	strStyle = "QPushButton{border:0;background:transparent;background-image: url(:/msgbox/confirm_normal.png);}"
               "QPushButton:hover{border:0;background:transparent;background-image: url(:/msgbox/confirm_hover.png);}";
    	ui->btn_confirm->setStyleSheet(strStyle);
    
    
    	// 根据参数,设在当前消息弹窗需要显示的图片(显示类型)
    	if(SA_SUCCESS == m_nTipType)
    	{
        	strStyle = "QLabel{border:0;background:transparent;background-image: url(:/msgbox/success_icon.png);}";
    	}
    	else if (SA_FAILED == m_nTipType)
    	{
        	strStyle = "QLabel{border:0;background:transparent;background-image: url(:/msgbox/error_icon.png);}";
    	}
    	else if (SA_WARNING == m_nTipType)
    	{
        	strStyle = "QLabel{border:0;background:transparent;background-image: url(:/msgbox/warning_icon.png);}";
    	}
    	else if (SA_TIPS == m_nTipType)
    	{
        	strStyle = "QLabel{border:0;background:transparent;background-image: url(:/msgbox/tips_icon.png);}";
    	}
    	else if (SA_QUESTION == m_nTipType)
    	{
        	strStyle = "QLabel{border:0;background:transparent;background-image: url(:/msgbox/question_icon.png);}";
    	}
    	ui->label_icon->setStyleSheet(strStyle);
    }
    

    也就是设置按钮个数和设置现实的图片!

  3. 实现按钮的槽函数

    private slots:
    	void on_btn_close_clicked();    // “叉”按钮槽函数
    	void on_btn_confirm_clicked();  // “是”按钮槽函数
    	void on_btn_cancel_clicked();   // “否”按钮槽函数
    
    void MessageBox::on_btn_close_clicked()
    {
    	// .exec()结束后返回0
    	done(0);
    	this->close();
    }
    
    void MessageBox::on_btn_confirm_clicked()
    {
    	// .exec()结束后返回1
    	done(1);
    	this->close();
    }
    
    void MessageBox::on_btn_cancel_clicked()
    {
    	// .exec()结束后返回0
    	done(0);
    	this->close();
    }
    

    当实现到这一步,说明已经自己写的messagebox可以运行了!

  4. 测试MessageBox
    在maindow的构造函数函数中写下代码:

    MessageBox *messagebox = new MessageBox(this);
    messagebox->exec();
    

在这里插入图片描述
运行后效果,感觉还可以喔,慢慢的成就感!
但是还不全面,还有很多地方要优化,例如设置成一个按钮时,两秒后自动关闭窗体的功能还没有写;还有这个窗体不能移动;还有提示语还不能设置;下面将开始优化!


四、优化代码

1).窗体移动

在MessageBox.h文件中:

  1. 添加头文件
    添加头文件:#include < QPoint >、#include < QMouseEvent >

  2. 添加私有变量:

    private:
    	QPoint m_pMousePoint;
    	bool m_bMousePressed;
    
  3. 重写鼠标移动事件方法

    protected:
    	void mouseMoveEvent(QMouseEvent *event) override;		// 鼠标移动
    	void mousePressEvent(QMouseEvent *event) override;		// 鼠标按下
    	void mouseReleaseEvent(QMouseEvent *event) override;	// 鼠标释放
    
    
    void MessageBox::mouseMoveEvent(QMouseEvent *event)
    {
    	// 如果鼠标是按下的
    	if(m_bMousePressed)
    	{
        	// 移动窗体
        	move(event->pos() - m_pMousePoint + pos());
    	}
    }
    
    void MessageBox::mousePressEvent(QMouseEvent *event)
    {
    	// 鼠标左键按下
    	if(event->button() == Qt::LeftButton)
    	{
        	// 标志设置true
        	m_bMousePressed = true;
        	// 获取当前窗体位置
        	m_pMousePoint = event->pos();
    	}
    }
    
    void MessageBox::mouseReleaseEvent(QMouseEvent *event)
    {
    	// 鼠标左键释放(松开)
    	if(event->button() == Qt::LeftButton) {
        	// 鼠标松开,标志设在false
        	m_bMousePressed = false;
    	}
    }
    
  4. 不出意外的话,到这一步,窗体已经可以移动了,赶快去试试吧!

2). 设置消息弹窗提示语

在MessageBox.h文件中:

  1. 添加公共方法:

    public:
    	void SetTips(const std::string& strTips);
    
  2. 实现它设置提示语

    void MessageBox::SetTips(const std::string &strTips)
    {
    	ui->label_tips->setText(strTips.c_str());
    }
    
  3. 测试
    在maindow的构造函数中添加代码:

    MessageBox *messagebox = new MessageBox(this);
    messagebox->SetTips("你好,测试提示语!");
    messagebox->exec();
    

在这里插入图片描述
可以发现,已经可以设置提示语了!

3). 两秒后自动关闭窗体

在MessageBox.h文件中:

  1. 添加头文件
    添加头文件:#include < thread >、#include < unistd.h >

  2. 添加私有变量:

    private:
        std::thread *t1;	// C++线程
    

    并在构造函数的最上方进行初始化:t1 = nullptr;
    一定要在构造函数里的最上方进行初始化,否则接下来的操作会导致软件崩溃!

  3. 添加两个私有成员方法
    一个用来定义线程,一个用来被线程执行

    private:
    	// 设在sec秒后关闭窗体
    	void _startTimerClose(int sec = 2);
    	// 线程执行的函数,用于计时关闭窗体
    	void ticktack(int sec = 2);
    

    实现这两个私有成员方法

    void MessageBox::_startTimerClose(int sec)
    {
    	if (t1) {
        	delete t1;
        	t1 = nullptr;
    	}
    
    	// 定义线程
    	t1 = new std::thread(&MessageBox::ticktack, this, sec);
    	t1->detach();
    }
    
    void MessageBox::ticktack(int sec)
    {
    	int secTicktack = 0;
    	while (false == this->isHidden()) {     // 如果窗体是显示的
    
        	// 判断秒数相等,则关闭窗体
        	if (secTicktack == sec) {
            	done(1);
            	this->close();
            	break;
        	}
    
        	sleep(1);   // Sleep(1);
        	secTicktack++;
        	printf("%d   -   ticktack = %d\n", sec, secTicktack);
    	}
    }
    
  4. 重写窗体显示事件方法

    protected:
    	// 窗体show前的事件操作
    	void showEvent(QShowEvent *) override;
    
    
    void MessageBox::showEvent(QShowEvent *)
    {
    	// 判断窗体类型,启动线程计时关闭窗体
    	if(MSG_TYPE::SA_OK == m_nType) {
        	_startTimerClose(2);
    	}
    }
    
  5. 析构函数
    在析构函数中释放线程内存

    MessageBox::~MessageBox()
    {
    	if (t1) delete t1;
    	delete ui;
    }
    

好了,到了这里,代码已经写完了,可以去测试了,不出意外的话,只要设置的是MSG_TYPE::SA_OK类型的提示窗体,那么,两秒后就会自动关闭窗体!
测试代码:

MessageBox *messagebox = new MessageBox(this, MSG_TYPE::SA_OK, MSG_TIP_TYPE::SA_SUCCESS);
messagebox->SetTips("你好,测试提示语!");
messagebox->exec();

在这里插入图片描述

题外话,可以使用线程池进行操作:(两秒后关闭窗体)

std::shared_ptr<ThreadPoolEx> m_pThreadPools;

m_pThreadPools = std::make_shared<ThreadPoolEx>(1);
m_pThreadPools->enqueue([=](){sleep(2); close();});

在构造函数隐藏按钮的if判断里加上上面两行代码即可


五、封装调用

接下来,调用代码封装成一个函数,方便调用!

在mainwindow中添加方法:

public:
	int ShowMsgBox(const std::string strTips, MSG_TYPE nType, const MSG_TIP_TYPE nTipType);	

实现该方法:

int MainWindow::ShowMsgBox(const std::string strTips, MSG_TYPE nType, const MSG_TIP_TYPE nTipType)
{
    MessageBox* pMsgBox = new MessageBox(nullptr, nType, nTipType); // 定义指针,不需要手动释放内存,因为我们设置了窗体关闭时自动释放内存
    pMsgBox->SetTips(strTips.c_str());      // 设置提示语
    pMsgBox->setModal(true);                // 设置为模态
    int nRes = pMsgBox->exec();             // 运行
    return nRes;                            // 返回值
}

简单测试:

int res = ShowMsgBox("实现了代码封装,调用起来更加简单了!", MSG_TYPE::SA_OKCANCEL, MSG_TIP_TYPE::SA_FAILED);

在这里插入图片描述
已经完美的调用了,看起来还不错喔,哈哈!


六、返回值

这里再说一下返回值。

代码中,我们设置了,只有点击“是”按钮,或者“确定”按钮,或者两秒后自动关闭窗体才会返回1,其他情况都是返回0!

根据这个特性,我们就可以进行具体判断使用了!

例如:

int res = ShowMsgBox("您却要退出程序吗?", MSG_TYPE::SA_OKCANCEL, MSG_TIP_TYPE::SA_QUESTION);
if (res == 1) {
    printf("退出程序!\n");
} else {
    printf("返回值:%d\n", res);
}

在这里插入图片描述

当点击"是":
在这里插入图片描述
当点击"否":
在这里插入图片描述


七、MessageBox代码

  1. MessageBox.h

    #ifndef MESSAGEBOX_H
    #define MESSAGEBOX_H
    
    #include <QDialog>
    #include <QPoint>
    #include <QMouseEvent>
    
    #include <thread>
    #include <unistd.h>
    
    namespace Ui {
    class MessageBox;
    }
    
    // 设在按钮个数
    enum MSG_TYPE
    {
        SA_OK           = 0,    // 只有一个“确定”按钮,且两秒钟后自动关闭消息窗口
        SA_OKCANCEL     = 1,    // 一个“是”按钮,一个“否”按钮
        SA_OKS          = 2     // 只有一个“确定”按钮,不会自动关闭消息窗口
    };
    
    // 设在提示的类型
    enum MSG_TIP_TYPE
    {
        SA_SUCCESS      = 0,    // 完成
        SA_FAILED       = 1,    // 错误
        SA_WARNING      = 2,    // 警告
        SA_TIPS         = 3,    // 提示
        SA_QUESTION     = 4     // 未知
    };
    
    
    class MessageBox : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit MessageBox(QWidget *parent = nullptr,MSG_TYPE nType = SA_OKCANCEL,MSG_TIP_TYPE nTipType = SA_TIPS);
        ~MessageBox();
    
        // 设置提示语
        void SetTips(const std::string& strTips);
    
    private:
        // 设在sec秒后关闭窗体
        void _startTimerClose(int sec = 2);
        // 线程执行的函数,用于计时关闭窗体
        void ticktack(int sec = 2);
    
    
    private slots:
        void on_btn_close_clicked();    // “叉”按钮槽函数
        void on_btn_confirm_clicked();  // “是”按钮槽函数
        void on_btn_cancel_clicked();   // “否”按钮槽函数
    
    
    protected:
        void mouseMoveEvent(QMouseEvent *event) override;       // 鼠标移动
        void mousePressEvent(QMouseEvent *event) override;      // 鼠标按下
        void mouseReleaseEvent(QMouseEvent *event) override;    // 鼠标释放
    
        // 窗体show前的事件操作
        void showEvent(QShowEvent *) override;
    
    private:
        Ui::MessageBox *ui;
        int m_nType;
        int m_nTipType;
        QPoint m_pMousePoint;
        bool m_bMousePressed;
        std::thread *t1;
    };
    
    #endif // MESSAGEBOX_H
    
  2. MessageBox.cpp

    #include "MessageBox.h"
    #include "ui_MessageBox.h"
    
    MessageBox::MessageBox(QWidget *parent, MSG_TYPE nType, MSG_TIP_TYPE nTipType) :
        QDialog(parent),
        ui(new Ui::MessageBox)
    {
        ui->setupUi(this);
    
        m_nType = nType;
        m_nTipType = nTipType;
        t1 = nullptr;
    
        setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
        // 设置窗体关闭时自动释放内存
        this->setAttribute(Qt::WA_DeleteOnClose);
    
    
        // 设在按钮
        if(MSG_TYPE::SA_OK == m_nType)
        {
            ui->btn_cancel->setVisible(false);  // 隐藏“否”按钮
            ui->btn_confirm->setText("确定");
        }
        else if(MSG_TYPE::SA_OKCANCEL == m_nType)
        {
            ui->btn_cancel->setVisible(true);   // 显示“否”按钮
            ui->btn_confirm->setText("是");
        }
        else if (MSG_TYPE::SA_OKS == m_nType)
        {
            ui->btn_cancel->setVisible(false);  // 隐藏“否”按钮
            ui->btn_confirm->setText("确定");
        }
    
        // 设在两个按钮样式,这样设在效果:当鼠标移动到按钮上方,会切换对应设在的图片,移开后又会设在回来
        QString strStyle = "QPushButton{border:0;background:transparent;background-image: url(:/msgbox/cancel_normal.png);}"
                           "QPushButton:hover{border:0;background:transparent;background-image: url(:/msgbox/cancel_hover.png);}";
        ui->btn_cancel->setStyleSheet(strStyle);
    
        strStyle = "QPushButton{border:0;background:transparent;background-image: url(:/msgbox/confirm_normal.png);}"
                   "QPushButton:hover{border:0;background:transparent;background-image: url(:/msgbox/confirm_hover.png);}";
        ui->btn_confirm->setStyleSheet(strStyle);
    
    
        // 根据参数,设在当前消息弹窗需要显示的图片(显示类型)
        if(SA_SUCCESS == m_nTipType)
        {
            strStyle = "QLabel{border:0;background:transparent;background-image: url(:/msgbox/success_icon.png);}";
        }
        else if (SA_FAILED == m_nTipType)
        {
            strStyle = "QLabel{border:0;background:transparent;background-image: url(:/msgbox/error_icon.png);}";
        }
        else if (SA_WARNING == m_nTipType)
        {
            strStyle = "QLabel{border:0;background:transparent;background-image: url(:/msgbox/warning_icon.png);}";
        }
        else if (SA_TIPS == m_nTipType)
        {
            strStyle = "QLabel{border:0;background:transparent;background-image: url(:/msgbox/tips_icon.png);}";
        }
        else if (SA_QUESTION == m_nTipType)
        {
            strStyle = "QLabel{border:0;background:transparent;background-image: url(:/msgbox/question_icon.png);}";
        }
        ui->label_icon->setStyleSheet(strStyle);
    }
    
    MessageBox::~MessageBox()
    {
        if (t1) delete t1;
        delete ui;
    }
    
    void MessageBox::SetTips(const std::string &strTips)
    {
        ui->label_tips->setText(strTips.c_str());
    }
    
    void MessageBox::_startTimerClose(int sec)
    {
        if (t1) {
            delete t1;
            t1 = nullptr;
        }
    
        // 定义线程
        t1 = new std::thread(&MessageBox::ticktack, this, sec);
        t1->detach();
    }
    
    void MessageBox::ticktack(int sec)
    {
        int secTicktack = 0;
        while (false == this->isHidden()) {     // 如果窗体是显示的
    
            // 判断秒数相等,则关闭窗体
            if (secTicktack == sec) {
                done(1);
                this->close();
                break;
            }
    
            sleep(1);   // Sleep(1);
            secTicktack++;
            printf("%d   -   ticktack = %d\n", sec, secTicktack);
        }
    }
    
    void MessageBox::on_btn_close_clicked()
    {
        // .exec()结束后返回0
        done(0);
        this->close();
    }
    
    void MessageBox::on_btn_confirm_clicked()
    {
        // .exec()结束后返回1
        done(1);
        this->close();
    }
    
    void MessageBox::on_btn_cancel_clicked()
    {
        // .exec()结束后返回0
        done(0);
        this->close();
    }
    
    void MessageBox::mouseMoveEvent(QMouseEvent *event)
    {
        // 如果鼠标是按下的
        if(m_bMousePressed)
        {
            // 移动窗体
            move(event->pos() - m_pMousePoint + pos());
        }
    }
    
    void MessageBox::mousePressEvent(QMouseEvent *event)
    {
        // 鼠标左键按下
        if(event->button() == Qt::LeftButton)
        {
            // 标志设置true
            m_bMousePressed = true;
            // 获取当前窗体位置
            m_pMousePoint = event->pos();
        }
    }
    
    void MessageBox::mouseReleaseEvent(QMouseEvent *event)
    {
    
        // 鼠标左键释放(松开)
        if(event->button() == Qt::LeftButton) {
            // 鼠标松开,标志设在false
            m_bMousePressed = false;
        }
    
    }
    
    void MessageBox::showEvent(QShowEvent *)
    {
        // 判断窗体类型,启动线程计时关闭窗体
        if(MSG_TYPE::SA_OK == m_nType) {
            _startTimerClose(2);
        }
    }
    

八、总结

csdn:
https://download.csdn.net/download/cpp_learner/85309167

百度云:
链接:https://pan.baidu.com/s/1_wUpOD6WYnDS9T5dPG-p0Q?pwd=1234
提取码:1234

总体已经完成了,可能还会有一些细节还没有设置好,可以根据自己的需求进行修改设置!

到了这里,已经讲完了,不知道看了这篇博客的朋友学会了没有呢?

其实也不算太难是吧,并没有什么复杂的代码,而且窗体布局也是很简单,就是设置样式那里比较难,我也不是很懂这方面的知识…

所以呢,还没学会的朋友回过头来好好再看一遍吧,学会了这些,对自己以后工作做项目还是有一定的帮助的!

  • 34
    点赞
  • 129
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpp_learners

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值