Bootstrap

QT第四课------QT窗口

作者前言

🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
​🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言、C++和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂


QMainWindow

前面我们学习的控件,都是基于QWidget,这个是作为窗口的一部分
一个完整的Qt窗口是通过 QMainWindow类 来实现的
QMainWindow 是⼀个为⽤⼾提供主窗⼝程序的类,继承⾃ QWidget 类,并且提供了⼀个预定义的
布局。QMainWindow 包含 ⼀个菜单栏(menu bar)、多个⼯具栏(tool bars)、多个浮动窗⼝(铆
接部件)(dock widgets)、⼀个状态栏(status bar) 和⼀个 中⼼部件(central widget),它是许多应
⽤程序的基础,如⽂本编辑器,图⽚编辑器等。如下图为 QMainwindow 中 各组件所处的位置
在这里插入图片描述
(其中所在的颜色框内,是可以把对应的控件放在其中的,例如:菜单只能放在QT窗口的红色区域内 )
如果不太了解,我以Qt crate为例子
在这里插入图片描述
接下来我们创建QT文件的时候,不是创建QWidget窗口,而是QMainWindow窗口
如图:
在这里插入图片描述
当我们运行起来就会发现,窗口和前面我们创建的QWidget窗口的效果一样,
如图:
在这里插入图片描述
当我们打开ui文件,就会发现, ui文件和QWidget的ui文件不一样,
效果如下:
在这里插入图片描述
我们接着看到右上角的对象树上, 有如下:

在这里插入图片描述
创建了菜单栏和状态栏,这就和QWidget窗口形成了鲜明对比;

QMenuBar

Qt 中的菜单栏是通过 QMenuBar 这个类来实现的。⼀个主窗⼝最多只有⼀个菜单栏。位于主窗口顶部、主窗口标题栏下⾯。
在这里插入图片描述
这里的菜单项不是使用QMenuBarItem来表示的, 而是使用Qaction(菜单项)
所以我们创建菜单的总体思路如下:
在这里插入图片描述
下面我们写一个简单的代码,写一个可以增加菜单的代码

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QMenuBar *menu = CreateMenu(this);
    //创建网格布局
    QGridLayout  *layou1 =  new QGridLayout();
    //创建中心部件
    QWidget* w = new QWidget();
    this->setCentralWidget(w);
    QGridLayout  *  menuButton= CreateLayout("添加", "输入菜单名称", "菜单", menu);
    QGridLayout  *  actionButton=CreateLayout( "添加", "输入菜单项名称", "菜单项",menu);
    layou1->addLayout(menuButton,0,0);
    layou1->addLayout(actionButton,1,0);
    w->setLayout(layou1);
}

MainWindow::~MainWindow()
{
    delete ui;
}

QMenuBar * MainWindow::CreateMenu(MainWindow * parent)
{
    //创建菜单栏
    QMenuBar *menu = new QMenuBar();
    //添加菜单
    QMenu* menuchild = new QMenu("文件", menu);//对象树释放,不包含该添加控件
    menu->addMenu(menuchild);
    //往菜单里面添加菜单项
    QAction * acton = new QAction("打开", menuchild);//对象树释放,不包含该添加控件
    menuchild->addAction(acton);
    parent->setMenuBar(menu);
    return menu;

}




QGridLayout  * MainWindow::CreateLayout(QString buttnName, QString input, QString laberName,QMenuBar *menu)
{

    //创建网格布局

    QGridLayout  *layou1 =  new QGridLayout();
    QPushButton * button = new QPushButton(buttnName);
    QLineEdit * inputBox = new QLineEdit();
    inputBox->setPlaceholderText(input);
    QLabel  * laber = new QLabel(laberName);
    layou1->addWidget(laber, 0,0);
    layou1->addWidget(inputBox, 0,1);
    layou1->addWidget(button, 0,2);

//判断是菜单还是菜单项
    if(a == 1)
        connect(button, &QPushButton::clicked, this, [=]()
        {
            QString name = inputBox->text();
             if(!name.isEmpty())
             {
                QMenu* me= new QMenu(name, this);
                menu->addMenu(me);//添加菜单
                qDebug()<< name;
             }
             a = 0;
        });
    else
        connect(button, &QPushButton::clicked, this, [=]()
        {
            QString name = inputBox->text();
             if(!name.isEmpty())
             {
                qDebug()<< name;
             }
        });

    return layou1;
}

效果图:
在这里插入图片描述
注意(菜单项的代码是不能添加菜单项,只是一个效果)

由于没有获取当前的QMenu的函数, 需要使用到信号函数,

下面列举一下
QMenu的信号函数:
aboutToShow()
描述:在菜单即将显示之前发出。
用途:可以用于在菜单显示之前进行一些准备工作,比如动态更新菜单内容。

aboutToHide()
描述:在菜单即将隐藏之前发出。
用途:可以用于清理或保存状态。
triggered(QAction *action)
描述:当菜单中的某个动作被触发时发出。
用途:用于处理用户选择菜单项的事件。
hovered(QAction *action)
描述:当鼠标悬停在菜单项上时发出。
用途:可以用于更新界面或显示额外信息。

QAction的信号函数:
triggered(bool checked = false)
描述:当 QAction 被触发时发出,通常是用户点击菜单项或工具栏按钮。
用途:用于处理用户选择该动作时的事件

toggled(bool checked)
描述:当 QAction 的选中状态发生变化时发出。此信号通常用于复选框或切换按钮。
用途:用于更新界面或处理状态变化。

注意:QMenuBar是没有信号函数的

在上面的代码我们进一步改造的写一个添加菜单项的函数以及点击菜单项的信号槽

QGridLayout  * MainWindow::CreateLayout(QString buttnName, QString input, QString laberName,QMenuBar *menu)
{

    //创建网格布局

    QGridLayout  *layou1 =  new QGridLayout();
    QPushButton * button = new QPushButton(buttnName);
    QLineEdit * inputBox = new QLineEdit();
    inputBox->setPlaceholderText(input);
    QLabel  * laber = new QLabel(laberName);
    layou1->addWidget(laber, 0,0);
    layou1->addWidget(inputBox, 0,1);
    layou1->addWidget(button, 0,2);

//判断是菜单还是菜单项
        connect(button, &QPushButton::clicked, this, [=,this]()
        {
            QString name = inputBox->text();
             if(!name.isEmpty())
             {
                QMenu* me= new QMenu(name, this);
                menu->addMenu(me);//添加菜单
                //添加一条添加菜单项的,选获取到当前的网格布局, 然后创建布局添加进去

                QHBoxLayout * horizontal = new QHBoxLayout();
                //
                QPushButton * button1 = new QPushButton("添加");
                QLineEdit * inputBox1 = new QLineEdit();
                QLabel  * laber = new QLabel("菜单项");
                inputBox1->setPlaceholderText("输入菜单项");
                horizontal->addWidget(laber);
                horizontal->addWidget(inputBox1 );
                horizontal->addWidget(button1);
                //弹出一个窗口
                QWidget * ww = new QWidget();
                ww->setLayout(horizontal);
                ww->show();
               connect(button1,&QPushButton::clicked, this, [=]
                {
                    //创建菜单项
                    QAction * action = new QAction(inputBox1->text());
                    me->addAction(action);
                    inputBox1->setText("");
                    connect(action, &QAction::triggered, this, [=]()
                    {
                        qDebug()<< action->text();
                    });
                });
                qDebug()<< name << this->centralWidget();

             }
        });

    return layou1;
}

效果:
在这里插入图片描述
当我们点菜单项就会输出菜单项的内容,

快捷键的设置

除了上面的代码, 我们还可以给菜单设置快捷键, 如果使用QShortCut来创建快捷键,有点小麻烦,
这里我们可以使用上古魔法,

 QAction * action = new QAction(inputBox1->text()+"(&F)");

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

就是在添加一个(&F)表示 Alt+F可以触发这个菜单项, 并不用创建QShortCut对象,

菜单嵌套子菜单

这个使用到addMenu这个函数, 形如:
代码如下:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //创建菜单栏
    QMenuBar * menuB = new QMenuBar(this);
    //创建菜单
    QMenu *menuchild = new QMenu("菜单",this);//对象树
    menuB->addMenu(menuchild);
    //创建子菜单
    QMenu *menuchild1 = new QMenu("子菜单",this);//对象树
    menuchild->addMenu(menuchild1);
    //创建菜单项
    QAction * menuaction = new QAction("退出(&Q)",this);
    menuchild1->addAction(menuaction);
    connect(menuaction, &QAction::triggered, this, [=]()
    {
        this->close();
    });

}

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

菜单项之间添加分割线

在菜单项之间可以添加分割线。分割线如下图所⽰,添加分割线是通过 QMenu 类 提供的
addSeparator() 函数来实现
在上面的代码中我们添加一个separator,

menuchild1->addAction(menuaction);
menuchild1->addSeparator();
    menuchild1->addAction(menuaction1);
    

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

在菜单项1 和菜单项2之间添加了分割线,可以更好的让其分组

插入图标

在我们使用一些菜单项的时候会有一些图标,让我们区分,
如图:
在这里插入图片描述
所以我们也可以添加一些图标进去,
代码如下:

 QPixmap img("://book.png");
     QIcon  icoimg(img);
    menuaction1->setIcon(icoimg);

效果如下:
在这里插入图片描述
注意:如果是QMenu去设置菜单,有时候会因为图标太大,覆盖文本的

新建的QMenuBar自动生成ui文件的QMenuBar的区别

在前面的代码中,我们都是直接创建一个新的 QMenuBar, 忽视了ui文件里面的
如图:
在这里插入图片描述

我们这样的写法会导致ui文件里面的旧的QMenuBar被挤出对象树,新的进入对象树, 进而导致旧的QmenuBar内存泄漏了,
为了防止这样的问题, 我们创建新的QMenuBar不能使用上面的写法, 可以使用如下:

QMenuBar* menuBar = this->menuBar();//如果有菜单栏就返回,没有就创建新的 

如果我们创建很多个菜单栏,就会导致旧的被挤出对象树,这就可以验证,一个QMainwindow窗口只能有一个菜单栏

工具栏

⼯具栏是应⽤程序中集成各种功能实现快捷键使⽤的⼀个区域。可以有多个,也可以没有,它并不是应⽤程序中必须存在的组件。它是⼀个可移动的组件,它的元素可以是各种窗⼝组件,它的元素通常以图标按钮的⽅式存在。如下图为⼯具栏的⽰意图:

在这里插入图片描述
简单的说就是,工具栏需不需要,要看自己, 并且在ui文件中也没有创建,需要我们手动创建,工具栏可以有很多个

创建工具栏

调⽤ QMainWindow类 的 addToolBar() 函数来创建⼯具栏,每增加⼀个⼯具栏都需要调⽤⼀次该函数。
我们创建工具项使用的类是QAction和菜单项是一样的
代码如下:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    CreatrTool(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::CreatrTool(QMainWindow*parent)
{
    //创建工具栏
    QToolBar * tool = new QToolBar(parent);
    //创建菜单项
    QAction *toolAction1 = new QAction("文件", parent);
    QAction *toolAction2 = new QAction("保存", parent);
    toolAction1->setIcon(QIcon("://file.png"));
    toolAction2->setIcon(QIcon("://presetvation.png"));
    tool->addAction(toolAction1);
    tool->addAction(toolAction2);
    //添加到mainwindow窗口的正上方
    parent->addToolBar(Qt::TopToolBarArea,tool);
}

效果图:
在这里插入图片描述
可以看出,我们创建的工具项会被图标覆盖, 这个是因为我们的工具项的空间有限, 但是文本不会因为覆盖而消失,而是转换成Tooltip(文本提示), 我们也可以自己进行设置,

tooltip

如:

QString name("打开文件");
    toolAction1->setToolTip(name);

菜单里面添加工具项

除此之外, 我们还可以这这个工具项添加到菜单栏那里, 这样就可以工具栏和菜单栏里面的菜单项效果是一样的,

    //创建菜单
    QMenu * menu = new QMenu("文件",parent);
    menu ->addAction(toolAction1);
    menu ->addAction(toolAction2);
    parent->menuBar()->addMenu(menu);

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

工具栏的位置设置

​还有就是我们可以通过控制给mianwindow窗口设置工具栏的时候,调整方向
Qt::LeftToolBarArea 停靠在左侧
• Qt::RightToolBarArea 停靠在右侧
• Qt::TopToolBarArea 停靠在顶部
• Qt::BottomToolBarArea 停靠在底部
• Qt::AllToolBarAreas 以上四个位置都可停靠

我们添加工具栏的时候除了使用QMainWindow的addToolBar()来设置位置,还可以使用QToolBar类的函数setAllowedAreas(),来设置位置,
addToolBar()主要的设置程序运行后,工具栏的初始位置, 而setAllowedAreas()主要是设置工具栏能停靠在哪个范围,也就是,我们移动工具栏的时候能放在的位置

如:

 //规定工具栏只能在右边
    tool->setAllowedAreas(Qt::RightToolBarArea);
    //添加到mainwindow窗口,初始化位置为上面
    parent->addToolBar(Qt::TopToolBarArea,tool);

如图:
在这里插入图片描述
这里设置初始化的位置为上面, 当我们放置的时候,只能放置到右边, 其他位置放置不了工具栏吗

设置浮动属性

我们在移动工具栏的时候,就会发现,我们可以随便移动到任意位置,这个工具栏都会悬浮在最上面,
⼯具栏的浮动属性可以通过 QToolBar类 提供的 setFloatable()函数 来设置。setFloatable()函数原
型为:
void setFloatable (bool floatable)
参数:
true:浮动
false:不浮动
代码如下:

//是否允许浮动
    tool->setFloatable(false);

当我们移动到其他地方去(除了可以放置的位置)都会浮动不了

设置移动属性

设置⼯具栏的移动属性可以通过 QToolBar类 提供的 setMovable()函数 来设置。setMovable()函数
原型为:
void setMovable(bool movable)
参数:
true:移动
false:不移动
代码如下:

//是否可以移动
    tool->setMovable(false);

当设置了不能移动,就会直接固定死了

状态栏

状态栏的创建是通过 QMainWindow 类 提供的 statusBar() 函数来创建;
对于的属性及方法:
属性
message: 显示当前消息的文本。
sizeGripEnabled: 控制状态栏是否显示大小调整手柄。
style: 状态栏的样式。
方法
showMessage(const QString &message, int timeout = 0): 显示一条消息,超时后自动消失。
clearMessage(): 清除当前显示的消息。
addWidget(QWidget *widget, int stretch = 0): 在状态栏中添加一个小部件(从左往右添加)。
addPermanentWidget():从左往右添加一个控件,
removeWidget(QWidget *widget): 从状态栏中移除指定的小部件。
currentMessage(): 获取当前显示的消息

⽰例如下:


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //创建一个状态栏
    QStatusBar * statu = this->statusBar();
    //给窗口添加状态栏
    this->setStatusBar(statu);
    //创建标签
    QLabel * laber = new QLabel("右提示");
    statu->addWidget(new QLabel("左提示"),1);//设置拉伸系数为1
    statu->addPermanentWidget(laber,5);//设置拉伸系数为5
    statu->showMessage("临时提示",3000);// 3000表示存在三秒,如果为0就是永久存在



}

效果图:
在这里插入图片描述
除了可以进行添加这些,还可以添加很多, 比如进度条progressBar…等

浮动窗⼝(铆接部件)

在 Qt 中,浮动窗⼝也称之为铆(mao )接部件。浮动窗⼝是通过 QDockWidget类 来实现浮动的功能。浮动窗⼝⼀般是位于核⼼部件的周围,可以有多个,
下面我们简单的写一个代码

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //创建铆接部件(子窗口)
    QDockWidget * dock= new QDockWidget();
    this->addDockWidget(Qt::LeftDockWidgetArea,dock);

}

效果:
在这里插入图片描述
可以看到有一个窗口
**但是如果我们往这个窗口里面添加控件, 不能直接添加, 需要我们创建一个QWidget窗口, 然后把需要添加的控件,添加到这个窗口中, 然后我们把这个Qwidget窗口添加到子窗口中去就行,**简单的理解就是一个dockwidget只能添加一个QWidget

代码如下:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //创建铆接部件(子窗口)
    QDockWidget * dock= new QDockWidget();
    this->addDockWidget(Qt::LeftDockWidgetArea,dock);
    //创建一个新的QWidget
    QWidget * newWideg = new QWidget();
    //创建一个布局
    QVBoxLayout * verticalLayout = new QVBoxLayout();
    //创建一个标签
    QLabel * laber = new  QLabel("这是一个标签");
    //创建一个按钮
    QPushButton  * button = new QPushButton("按钮");
    //添加到布局
    verticalLayout->addWidget(laber);
    verticalLayout->addWidget(button);
    // 布局添加到QWidget
    newWideg ->setLayout(verticalLayout);
    //QWidet添加到QDockWidget
    dock ->setWidget(newWideg);
}

效果如下:
在这里插入图片描述
可以看到效果

设置停靠的位置

这个铆接部件还可以设置位置, 跟工具栏的设置大同小异
这里就不过多写代码了

对话框

对话框是 GUI 程序中不可或缺的组成部分。⼀些不适合在主窗⼝实现的功能组件可以设置在对话框中。对话框通常是⼀个顶层窗⼝,出现在程序最上层,⽤于实现短期任务或者简洁的⽤⼾交互。Qt常⽤的内置对话框有:QFiledialog(⽂件对话框)、QColorDialog(颜⾊对话框)、QFontDialog(字体对话框)、QInputDialog (输⼊对话框)和 QMessageBox(消息框) 。

前面我们认识的窗口有QWidget、QMainWidget 以及QDialog

对话框分为 模态对话框⾮模态对话框。
同理我们创建为文件的时候选择的是,如图,
在这里插入图片描述
但是实际情况, 不会让对话框作为一个主窗口,而是在一些比如QMainWidget主窗口里面创建一些对话框出来,下面我们还是以创建QMainWidget主窗口为主,

模态对话框显示

模态对话框指的是:显⽰后⽆法与⽗窗⼝进⾏交互,是⼀种阻塞式的对话框。使⽤ QDialog::exec() 函数 调⽤。
模态对话框适⽤于必须依赖⽤⼾选择的场合,⽐如消息显⽰,⽂件选择,打印设置等。

下面我们写一个简单的对话框

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //创建一个菜单栏
    QMenuBar * menuBar = this->menuBar();
    this->setMenuBar(menuBar);
    //添加菜单
    QMenu * menu1 = new QMenu("文件");
    QMenu * menu2 = new QMenu("编辑");
    QMenu * menu3 = new QMenu("关于");
    //添加到菜单栏
    menuBar->addMenu(menu1);
    menuBar->addMenu(menu2);
    menuBar->addMenu(menu3);
    //添加菜单项
    QAction * action = new QAction("新建");
    menu1->addAction(action);
    //给菜单项设置静态对话框
    connect(action, &QAction::triggered, this,[=]()
    {
        //创建一个静态对话框
        //QDialog * dialog = new QDialog(this);
        QDialog * dialog (this);
        dialog->setWindowTitle("对话框");
        dialog->resize(200,300);
        dialog->exec();
		//这里创建的是在栈上创建的, 不是在堆
    });
}

效果:
在这里插入图片描述
模态对话框通常在栈上创建

非模态对话框显示

当我们细心就会发现,如果我们创建的这个对话框是在栈上创建的, 当我们每次点击这个新建,就会创建一个新的对话框,这样就会很容易导致内存泄漏, 为了防止这个事情的发生,我们需要释放掉这个内存, 所以我们释放掉的地方可以在客户关闭这个对话框的时候释放掉,
在QT中为了方便使用,QDialog写一个对于的函数setAttribute(),

dialog->setAttribute(Qt::WA_DeleteOnClose);//在客户关闭窗口,释放内存

这样就会关闭对话框就会释放掉内存

自定义对话框

我们可以自己写一个对话框,继承于QDialog
一般有两种方式, 一种是纯代码的方式, 一种是界面操作(ui文件)
纯代码方式:
我们创建一个类
在这里插入图片描述
如下是我创建的类
在这里插入图片描述
代码:
.h

#include<QWidget>
#include<QDialog>
#include<QPushButton>
#include<QLabel>
#include<QVBoxLayout>
struct My_Dialong :QDialog
{
    Q_OBJECT//可以关联信号和槽
public:
    My_Dialong(QWidget *parent = nullptr);
private:

};


#endif // MY_DIALONG_H

.cpp

My_Dialong::My_Dialong(QWidget *parent)
    :QDialog(parent)
{
    //创建布局
    QVBoxLayout * verticalLayout = new QVBoxLayout();

    //创建标签
    QLabel * label = new QLabel("这个一个标签");
    //创建按钮
    QPushButton * button = new QPushButton("按钮");
    verticalLayout->addWidget(label);
    verticalLayout->addWidget(button);
    //添加进去
    setLayout(verticalLayout);
    resize(200,300);

}

mainwidget.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , dialog(new My_Dialong)
{
    ui->setupUi(this);
    dialog->show();
}

MainWindow::~MainWindow()
{
    delete ui;
}

效果如下:
在这里插入图片描述
ui文件
首先创建一个ui文件
在这里插入图片描述
如下为我创建的ui文件
在这里插入图片描述
.h

#ifndef DIALOG_H
#define DIALOG_H

#include"my_dialong.h"
#include"ui_dialog.h"
namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = nullptr);
    ~Dialog();

private:
    Ui::Dialog *ui;
};

#endif // DIALOG_H

.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
}

Dialog::~Dialog()
{
  delete ui;
}

mainWidget.cpp

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , dialog(new My_Dialong)
{
    ui->setupUi(this);
    dialog->show();
    //dialog->setAttribute(Qt::WA_DeleteOnClose);
    //创建一个对话框(ui文件的)

    Dialog * di  = new Dialog();
    di->setAttribute(Qt::WA_DeleteOnClose);
    di->show();


}

MainWindow::~MainWindow()
{
    delete ui;
}

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

注意

⾮模态对话框⼀般在堆上创建,这是因为如果创建在栈上时,弹出的⾮模态对话框就会⼀闪⽽过。同时还需要设置 Qt:WA_DeleteOnClose 属性,⽬的是:当创建多个⾮模态对话框时(如打开了多个⾮模态窗⼝),为了避免内存泄漏要设置此属性

modal

上面我们介绍了模态和非模态的显示
模态:弹出对话框之后,不能操作主窗口, 只有先完成对话框的操作之后,关闭窗口才能对主窗口进行操作(常用于特殊的场合)
非模态:弹出对话框之后,能操作主窗口, 无需完成对话框的操作之后,关闭窗口才能对主窗口进行操作
简单的理解就是,显示模态对话框需要用exec(),而显示非模态对话框用show(),
而控制一个对话框的模态性,是由modal来控制的,

参数
modal: 布尔值,true 表示设置为模态对话框,false 表示设置为非模态对话框。

代码如下:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //创建一个模态
    QDialog * dialog =new QDialog(this);
    dialog->resize(100,200);
//    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->setModal(true);

    QPushButton * button = new QPushButton("切换成非模态", dialog);
    //创建一个垂直布局
    QVBoxLayout * verticalLayout = new QVBoxLayout();
    verticalLayout->addWidget(button);
    dialog->setLayout(verticalLayout);
     dialog->show();
    connect(button,&QPushButton::clicked, this, [=]()
    {
        dialog->close();
        dialog->setModal(false);
        dialog->show();
    });

}

运行起来就会发现,可以进行模态和非模态的切换

Qt 内置对话框

Qt 提供了多种可复⽤的对话框类型,即 Qt 标准对话框。Qt 标准对话框全部继承于 QDialog类。常⽤标准对话框如下:
在这里插入图片描述

QMessageBox

消息对话框是应⽤程序中最常⽤的界⾯元素。消息对话框主要⽤于为⽤⼾提⽰重要信息,强制⽤户进⾏选择操作。(模态)
属性如下:
标题 (Title)
setWindowTitle(const QString &title)

文本 (Text)
setText(const QString &text)

附加信息 (Informative Text)
setInformativeText(const QString &text)

详细信息 (Detailed Text)
setDetailedText(const QString &text)

图标 (Icon)
setIcon(QMessageBox::Icon icon)
需要注意的是,icon除了我们自己设置图标, QT的MessageBox还提供了有四种图标
分别如下:
在这里插入图片描述
在这里插入图片描述

标准按钮 (Standard Buttons)
setStandardButtons(StandardButtons buttons)
StandardButtons是一个枚举类型,如下:
在这里插入图片描述
这些是标准按钮, 如果要自定义按钮的话, 需要使用addButton()函数,这个函数有两个参数, 第二个参数是一个枚举类型
如下:
在这里插入图片描述
当我们添加按钮进去,这个参数就是设置按钮的用途

默认按钮 (Default Button)
setDefaultButton(QAbstractButton *button)

窗口大小 (Size)
resize(int width, int height)

下面我们写一个简单消息对话框

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QMessageBox>
#include<QPushButton>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    //创建一个对话框
    QMessageBox * message = new QMessageBox(this);
    //设置对话框的内容
    message->setText("这是一条信息");
    //设置对话框的图标
    message->setIcon(QMessageBox::Warning);
    //设置按钮方法一
//    message->setStandardButtons(QMessageBox::No | QMessageBox::Help | QMessageBox::Cancel);
    //设置按钮方法二
    QPushButton * button =new QPushButton("按钮", message);
    message->addButton(button, QMessageBox::AcceptRole);
    message->setAttribute(Qt::WA_DeleteOnClose);//
    message->setModal(true);
    message->show();

}

效果如下:
在这里插入图片描述
注意: 如果使用exec()来显示,会有一个特性, 代码运行到这一行会在运行到这里停止, 等待用户操作完,然后再执行后面的代码, 这样我们可以直接在后面释放这个内存, 就不用设置setA
如图:
在这里插入图片描述
我们还可以通过接收exec函数的返回值来确定这个用户点击的是哪个按钮, 这里的返回值就是按钮对于的value, 上面列举出来了

 int ret  = message->exec();
    if(ret == QMessageBox::AcceptRole)
         qDebug()<< "ok";

快速创建Message

在QMessageBox中, 有四个静态成员函数, 这四个静态成员函数,可以使我们创建四个不一样的对话框,
在这里插入图片描述
下面我们使用一个information的静态成员函数,来创建一个对话框

void MainWindow::on_pushButton_2_clicked()
{
    QMessageBox::information(this, "对话框标题", "对话内容", QMessageBox::Ok);
}

效果:

在这里插入图片描述

颜⾊对话框 QColorDialog

颜⾊对话框的功能是允许⽤⼾选择颜⾊。继承⾃ QDialog 类。
常⽤⽅法介绍:
1、 QColorDialog (QWidget *parent = nullptr) //创建对象的同时设置⽗对象
2、 QColorDialog(const QColor &initial, QWidget *parent = nullptr) //创建对象的同时通过QColor对象设置默认颜⾊和⽗对象
3、 void setCurrentColor(const QColor &color) //设置当前颜⾊对话框
4、 QColor currentColor() const //获取当前颜⾊对话框
5、 QColor getColor(const QColor &initial = Qt::white, QWidget *parent = nullptr, const QString &title = QString(), QColorDialog::ColorDialogOptions options = ColorDialogOptions()) //打开颜⾊选择对话框,并返回⼀个QColor对象
参数说明:
initial:设置默认颜⾊
parent:设置⽗对象
title:设置对话框标题
options:设置选项

6、 void open(QObject *receiver, const char *member) //打开颜⾊对话框

下面写一个简单颜色对话框

#include<QColorDialog>
#include<QColor>
#include<QDebug>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //创建一个颜色对话框
    QColorDialog * colorDialog = new QColorDialog(this);
    colorDialog->setAttribute(Qt::WA_DeleteOnClose);
    colorDialog->setModal(true);
    colorDialog->exec();
    qDebug()<< "当前选择的颜色为:"<< colorDialog->currentColor();
}

效果图:
在这里插入图片描述
输出出来的结果如下图:
在这里插入图片描述
ARGB第一个字母表示不透明度, 本来RGB的范围是0~255,这里表示的是(0~1)

一般情况下, 创建一个颜色对话框,都不会写成上面的样子, 通常会使用getColor()这个静态成员函数来快速创建对话框,
如下:

void MainWindow::on_pushButton_clicked()
{
      QColor color = QColorDialog::getColor(QColor(10,10,10), this, "颜色对话框标提");//获取到选择的颜色
      char colorchar[1024];
      sprintf(colorchar, "background-color: rgb(%d, %d, %d);", color.red(), color.green(), color.blue());
      QString a = QString::fromStdString(colorchar);
      this->setStyleSheet(a);
  }

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

⽂件对话框 QFileDialog

⽂件对话框⽤于应⽤程序中需要打开⼀个外部⽂件或需要将当前内容存储到指定的外部⽂件。

常⽤⽅法介绍:
1、打开⽂件(⼀次只能打开⼀个⽂件)
QString getOpenFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options())
2、打开多个⽂件(⼀次可以打开多个⽂件)
QStringList getOpenFileNames(QWidget *parent = nullptr, const QString &caption = QString(),const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter =nullptr,QFileDialog::Options options = Options())
3、 保存⽂件
QString getSaveFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options())
参数说明:
参数1:parent ⽗亲
参数2:caption 对话框标题
参数3:dir 默认打开的路径
参数4:filter ⽂件过滤

记住,这些方法是静态成员函数,不用创建对象,直接使用也是可以创建成功的

下面写一个简单代码

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //创建一个文件对话框
    QFileDialog *flog = new QFileDialog(this);
    //创建一个菜单栏
    QMenuBar *menuBar = this->menuBar();
    //创建一个菜单
    QMenu * menu = new QMenu("文件");
    menuBar->addMenu(menu);
    //创建两个菜单项
    QAction * openFile = new QAction("打开文件");
    QAction * saveFile = new QAction("保存文件");
    menu->addAction(openFile);
    menu->addAction(saveFile);
    this->setMenuBar(menuBar);
    connect(openFile, &QAction::triggered, this, [=]()
    {
         QString ftr = flog->getOpenFileName(this, "打开文件", "D:/QT/图标库", "l*.png");//找出以l开头,中间不管有多少字符, 最后以.png结尾的文件
         qDebug()<< ftr;

    });
    connect(saveFile, &QAction::triggered, this, [=]()
    {
         QString ftr = flog->getSaveFileName(this, "保存文件", "D:/QT/图标库", ".png");//保存.png的文件格式
         qDebug()<< ftr;

    });



}

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

字体对话框 QFontDialog

Qt 中提供了预定义的字体对话框类 QFontDialog,⽤于提供选择字体的对话框部件。
相关方法:
getFont():
有两个重载

static QFont getFont(bool *ok, QWidget *parent = nullptr);
static QFont getFont(bool *ok, const QFont &initial, QWidget *parent = nullptr, const QString &title = QString(), FontDialogOptions options = FontDialogOptions());

我们使用的是第二个
代码如下:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //创建一个字体对话框
    QFontDialog * fst= new QFontDialog(this);
    bool ok = true;
    QFont  a = fst->getFont(&ok, QFont("黑体"));
    qDebug()<< a;
    
}

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

输⼊对话框 QInputDialog

Qt 中提供了预定义的输⼊对话框类:QInputDialog,⽤于进⾏临时数据输⼊的场合。

常⽤⽅法介绍:
1、双精度浮点型输⼊数据对话框
double getDouble (QWidget *parent, const QString &title, const QString &label, double
value = 0, double min = -2147483647, double max = 2147483647, int decimals = 1, bool *ok
= nullptr, Qt::WindowFlags flags = Qt::WindowFlags());

2、整型输⼊数据对话框
int getInt (QWidget *parent, const QString &title, const QString &label, int value = 0, int
min = -2147483647, int max = 2147483647, int step = 1, bool *ok = nullptr, Qt::WindowFlags
flags = Qt::WindowFlags());
3、选择条⽬型输⼊数据框
QString getItem (QWidget *parent, const QString &title, const QString &label, const
QStringList &items, int current = 0, bool editable = true, bool *ok = nullptr,Qt::WindowFlags flags = Qt::WindowFlags(), Qt::InputMethodHints inputMethodHints =Qt::ImhNone) ;
参数说明:
parent:⽗亲
title:对话框标题
label:对话框标签
items:可供选择的条⽬

代码如下:

#include<QInputDialog>
#include<QStringList>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    QInputDialog::getInt(this,"整数","输入整数");
}

void MainWindow::on_pushButton_2_clicked()
{
     QInputDialog::getDouble(this,"浮点数","输入浮点数");
}

void MainWindow::on_pushButton_3_clicked()
{
    QStringList ch;
    ch.push_back("1111");
    ch.push_back("1111");
    ch.push_back("1111");
    ch.push_back("1111");
    QInputDialog::getItem(this,"浮点数","输入浮点数",ch);
}

效果图:
在这里插入图片描述
需要注意的是QStringlist就是和C++的list是相似的

总结

QT窗口中主要介绍了在QmainWidget中的布局

  1. 菜单栏(QMenuBar)=> 菜单(QMenu)=> 菜单项(QAction)
  2. 工具栏(QToolBar)=>菜单项(QAction)
  3. 铆接部件 (QDockWidget)=>创建新的widge=>添加布局=>添加控件
  4. 状态栏(QStatuBar)
  5. 对话框(Dailog)
;