【Qt学习笔记】(四)Qt窗口
Qt窗口
- 1 菜单栏
- 1.1 创建菜单栏
- 1.2 在菜单栏中添加菜单
- 1.3 创建菜单项
- 1.4 在菜单项之间添加分割线
- 1.5 给菜单项添加槽函数
- 1.6 给菜单项添加快捷键
- 2 工具栏
- 2.1 创建工具栏
- 2.2 设置停靠位置
- 2.3 设置浮动属性
- 2.4 设置移动属性
- 2.5 添加 Action
- 3 状态栏
- 3.1 状态栏的创建
- 3.2 在状态栏中显示实时消息
- 3.3 状态栏中放入控件
- 4 浮动窗口
- 4.1 浮动窗口的创建
- 4.2 给浮动窗口添加控件
- 5 对话框
- 5.1 对话框介绍
- 5.2 创建对话框
- 5.3 对话框的内存释放问题
- 5.4 自定义对话框
- 5.5 模态对话框与非模态对话框
- 5.6 Qt 内置对话框
- 5.6.1 消息对话框 QMessageBox
- 5.6.2 颜色对话框
- 5.6.3 文件对话框
- 5.6.4 字体对话框 QFontDialog
- 5.6.5 输入对话框 QInputDialog
Qt窗口是通过QMainWindow类来实现的。
QMainWindow是一个为用户提供主窗口程序的类,继承自QWidget类,并且提供了一个预定义的布局。QMainWindow包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个浮动窗口(铆接部件) (dock widgets)、一个状态栏(status bar)和一个中心部件(central widget),它是许多应用程序的基础,如文本编辑器,图片编辑器等。如下图为QMainwindow中各组件所处的位置:
1 菜单栏
Qt中的菜单栏是通过QMenuBar这个类来实现的。一个主窗口最多只有一个菜单栏。位于主窗口顶部、主窗口标题栏下面。.
菜单栏中包含菜单.菜单中包含菜单项.
1.1 创建菜单栏
在 ui 界面中,已经创建好了菜单栏,直接输入对应的菜单项即可。
也可以通过代码的方式去添加菜单栏
菜单栏的创建可以借助于QMainWindow类提供的menuBar()函数来实现。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建菜单栏 QMenuBar* menubar = this->menuBar(); //把菜单栏放入窗口中 this->setMenuBar(menubar); }
注意:
如果创建的代码是
QMenuBar* menubar = new QMenuBar();
在创建项目的时候,如果没有勾选自动生成 ui 文件,此时这种创建菜单栏的方式没有问题。但是如果勾选了自动生成 ui 文件,这行代码可能会引起内存泄漏。
原因是:程序已经创建好了一个 QMenuBar,当设置新的 QMenuBar 进来的时候,就会导致前者脱离 Qt 的对象树,导致无法自动释放内存。
如果窗口关闭,对象树释放,此时进程也就结束了,进程结束,自然所有的内存都回收给系统,上述的内存泄漏不会造成影响。但是如果这样的代码是出现在一个多窗口的程序中,如果涉及到窗口的频繁跳转切换(窗口频繁创建销毁),上述内存泄漏就会严重一些。但是实际上由于现在的计算机内存都比较充裕,上述的内存泄漏都还好。服务器程序相比于客户端程序更害怕内存泄漏。服务器要处理很多请求,每个请求泄漏一点,请求积累下来就会累计很多。所以,我们更希望代码写得规范一些。
//创建菜单栏 //1.如果 QMenuBar 已经存在,直接获取并返回 //2.如果 QMenuBar 不存在,就先创建一个新的,再返回 QMenuBar* menubar = this->menuBar(); //把菜单栏放入窗口中 //如果是获取到已经存在 QMenuBar ,这里的设置就是自己替换自己,仍然在对象树上 this->setMenuBar(menubar);
1.2 在菜单栏中添加菜单
创建菜单,并通过QMenu提供的addMenu() 函数来添加菜单。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建菜单栏 //QMenuBar* menubar = this->menuBar(); QMenuBar* menubar = new QMenuBar(); //把菜单栏放入窗口中 this->setMenuBar(menubar); //创建菜单 QMenu* menu1 = new QMenu("文件"); QMenu* menu2 = new QMenu("编辑"); QMenu* menu3 = new QMenu("构建"); //添加菜单到菜单栏中 menubar->addMenu(menu1); menubar->addMenu(menu2); menubar->addMenu(menu3); }
1.3 创建菜单项
在Qt中,并没有专门的菜单项类,可以通过QAction类,抽象出公共的动作。如在菜单中添加菜单项.
QAction可以给菜单栏使用,也可以给工具栏使用.
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建菜单栏 //QMenuBar* menubar = this->menuBar(); QMenuBar* menubar = new QMenuBar(); //把菜单栏放入窗口中 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* action1 = new QAction("open"); QAction* action2 = new QAction("close"); QAction* action3 = new QAction("create"); //将菜单项添加到菜单上 menu1->addAction(action1); menu1->addAction(action2); menu1->addAction(action3); }
1.4 在菜单项之间添加分割线
在菜单项之间可以添加分割线。分割线如下图所示,添加分割线是通过QMenu 类提供的addSeparator()函数来实现;
menu1->addAction(action1); menu1->addSeparator();//在 open 和 close 之间添加分割线 menu1->addAction(action2); menu1->addAction(action3);
可以使用 setIcon 函数来给每个菜单项添加一个图标。在第三章常用控件中介绍到,这里不在赘述。
1.5 给菜单项添加槽函数
在菜单项被点击的时候,会触发 triggered 这个信号,利用这个信号去触发对应的槽函数
connect(action1,&QAction::triggered,this,&MainWindow::handle); void MainWindow::handle() { qDebug() ui-setupUi(this); //创建菜单栏 //QMenuBar* menubar = this->menuBar(); QMenuBar* menubar = new QMenuBar(); //把菜单栏放入窗口中 this->setMenuBar(menubar); //创建菜单 QMenu* menu1 = new QMenu("文件(&F)"); QMenu* menu2 = new QMenu("编辑(&E)"); QMenu* menu3 = new QMenu("构建(&C)"); //添加菜单到菜单栏中 menubar->addMenu(menu1); menubar->addMenu(menu2); menubar->addMenu(menu3); //创建菜单项 QAction* action1 = new QAction("open(&O)"); QAction* action2 = new QAction("close"); QAction* action3 = new QAction("create"); //将菜单项添加到菜单上 menu1->addAction(action1); menu1->addSeparator();//在 open 和 close 之间添加分割线 menu1->addAction(action2); menu1->addAction(action3); //点击 open 的时候触发槽函数 connect(action1,&QAction::triggered,this,&MainWindow::handle); }
按 ALT + 快捷键触发快捷键
2 工具栏
工具栏是应用程序中集成各种功能实现快捷键使用的一个区域 。可以有多个,也可以没有,它并不是应用程序中必须存在的组件。它是一个可移动的组件,它的元素可以是各种窗口组件,它的元素通常以图标按钮的方式存在。如下图为工具栏的示意图:
2.1 创建工具栏
调用QMainWindow类的addToolBar()函数来创建工具栏,每增加一个工具栏都需要调用一次该函数。
如添加一个工具栏并加入一个 QAction
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QToolBar* toolBar1 = new QToolBar(this); this->addToolBar(toolBar1); }
2.2 设置停靠位置
工具栏停靠位置的设置有两种方式。-种是在创建工具栏的同时指定停靠的位置,另一种是通过
QToolBar类提供的setAllowedAreas()函数来设置。
在创建工具栏的同时,也可以设置工具栏的位置,其默认位置是在窗口的最上面;如上述代码,默认在最上面显示。工具栏允许停靠的区域由QToolBar类提供的allowAreas()函数决定,其中可以设置的位置包括:
- Qt::LeftToolBarArea停靠在左侧
- Qt::RightToolBarArea停靠在右侧
- Qt::TopToolBarArea停靠在顶部
- Qt::BottomToolBarArea 停靠在底部
- Qt::AllToolBarAreas 以上四个位置都可停靠
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QToolBar* toolBar1 = new QToolBar(this); this->addToolBar(toolBar1); //指定工具栏在左侧显示 this->addToolBar(Qt::LeftToolBarArea,toolBar1); }
在窗口创建出来后,工具栏的位置可以依靠鼠标进行拖动
方式二:使用QToolBar类提供的setAllowedAreas()函数设置允许停靠位置。如下示例:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QToolBar* toolBar1 = new QToolBar(this); this->addToolBar(toolBar1); //指定工具栏在左侧显示 this->addToolBar(Qt::LeftToolBarArea,toolBar1); //设置只允许在上侧和左侧停靠 toolBar1->setAllowedAreas(Qt::LeftToolBarArea | Qt::TopToolBarArea); }
2.3 设置浮动属性
如果鼠标拖到窗口的中间位置,工具栏就会浮动在中间位置。
工具栏的浮动属性可以通过QToolBar类提供的setFloatable()函数来设置。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QToolBar* toolBar1 = new QToolBar(this); this->addToolBar(toolBar1); //指定工具栏在左侧显示 this->addToolBar(Qt::LeftToolBarArea,toolBar1); //设置只允许在上侧和左侧停靠 toolBar1->setAllowedAreas(Qt::LeftToolBarArea | Qt::TopToolBarArea); //设置工具栏不允许浮动 toolBar1->setFloatable(false); }
2.4 设置移动属性
设置工具栏的移动属性可以通过QToolBar类提供的setMovable()函数来设置。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QToolBar* toolBar1 = new QToolBar(this); this->addToolBar(toolBar1); //指定工具栏在左侧显示 this->addToolBar(Qt::LeftToolBarArea,toolBar1); //设置只允许在上侧和左侧停靠 toolBar1->setAllowedAreas(Qt::LeftToolBarArea | Qt::TopToolBarArea); //设置工具栏不允许浮动 toolBar1->setFloatable(false); //设置工具栏不允许移动 toolBar1->setMovable(false); }
设置不允许移动后,鼠标无法拖动工具栏。
2.5 添加 Action
工具栏不仅可以添加Action,也可以添加一些控件,这里以添加 Action 为例
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QToolBar* toolBar1 = new QToolBar(this); this->addToolBar(toolBar1); //指定工具栏在左侧显示 this->addToolBar(Qt::LeftToolBarArea,toolBar1); //设置只允许在上侧和左侧停靠 toolBar1->setAllowedAreas(Qt::LeftToolBarArea | Qt::TopToolBarArea); //设置工具栏不允许浮动 toolBar1->setFloatable(false); QAction* action1 = new QAction("保存"); toolBar1->addAction(action1); }
3 状态栏
**状态栏是应用程序中输出简要信息的区域。**一般位于主窗口的最底部,-、一个窗口中最多只能有一个状态栏。在Qt中,状态栏是通过QStatusBar类来实现的。在状态栏中可 以显示的消息类型有:
- 实时消息:如当前程序状态
- 永久消息:如程序版本号,机构名称
- 进度消息:如进度条提示,百分百提示
3.1 状态栏的创建
状态栏和菜单栏一样,如果创建项目的时候勾选了创建 ui 界面,那么就会自动生成一个状态栏。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建状态栏,已经存在就调用存在的,不存在就创建 QStatusBar* stbar = this->statusBar(); //将状态栏设置到窗口中 this->setStatusBar(stbar); }
3.2 在状态栏中显示实时消息
//状态栏中显示 2 秒的消息 stbar->showMessage("这是一个状态消息",2000);
将后面的数字改为 0 ,则是永久显示
3.3 状态栏中放入控件
状态栏也可放入一些控件,这里以放入 label 为例
QLabel* label = new QLabel("这是一个标签",this); stbar->addWidget(label);
调整显示消息的位置
QLabel* label2 = new QLabel("这是一个标签2",this); stbar->addPermanentWidget(label2);
4 浮动窗口
在Qt中,浮动窗口也称之为铆接部件。浮动窗口是通过QDockWidget类来实现浮动的功能。浮动窗口一般是位于核心部件的周围,可以有多个。
4.1 浮动窗口的创建
浮动窗口的创建是通过QDockWidget类提供的构造方法QDockWidget()函数动态创建的;示例如下
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建浮动窗口 QDockWidget* dockwidget = new QDockWidget("浮动窗口",this); //将浮动窗口置于当前窗口中,同时设置停靠在左侧 addDockWidget(Qt::LeftDockWidgetArea,dockwidget); }
4.2 给浮动窗口添加控件
要想给浮动窗口内部添加一些控件,需要创建一个单独的 QWidget ,把要添加的控件加入到 QWidget 中,然后再把这个 QWidget 设置到 dockWidget 中。
ainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建浮动窗口 QDockWidget* dockwidget = new QDockWidget("浮动窗口",this); //将浮动窗口置于当前窗口中,同时设置停靠在左侧 addDockWidget(Qt::LeftDockWidgetArea,dockwidget); //创建一个 QWidget ,并加入到 dockWidget 中 QWidget* container = new QWidget(); dockwidget->setWidget(container); //创建一个标签和一个垂直的布局管理器,把布局管理器加入到 Qwidget 中 //再把控件加入到布局管理器中 QLabel* label = new QLabel("这是一个标签",this); QVBoxLayout* vlayout = new QVBoxLayout(); container->setLayout(vlayout); vlayout->addWidget(label); }
5 对话框
5.1 对话框介绍
对话框是GUI程序中不可或缺的组成部分。一些不适合在主窗口实现的功能组件可以设置在对话框中。对话框通常是一个顶层窗口,出现在程序最上层,用于实现短期任务或者简洁的用户交互。Qt常用的内置对话框有: QFiledialog (文件对话框)、QColorDialog (颜色对话框)、QFontDialog(字体对话框)、QInputDialog (输入对话框) 和QMessageBox (消息框)
5.2 创建对话框
在创建项目的时候,选择 QDialog
运行程序,可以看到通过基于 QDialog 作为父类创建出来的程序窗口和之前通过 QWidget 创建出来的非常相似。
在实际开发中,往往不会直接在创建项目的时候继承自 QDialog,而是在代码中创建其他的类,让其他的类继承 QDialog。主窗口不会作为一个对话框,而是在主窗口中产生一个对话框。
代码示例:主窗口中通过点击按钮,弹出一个新的对话框
创建项目时,选择 QMainWindow
添加一个按钮,并编写对应的槽函数
void MainWindow::on_pushButton_clicked() { //创建一个对话框 QDialog* dialog = new QDialog(this); //设置对话框大小 dialog->resize(400,300); //设置对话框标题 dialog->setWindowTitle("标题"); dialog->show(); }
运行程序,并点击按钮,即可弹出对话框
5.3 对话框的内存释放问题
在上述代码示例中,每次点击按钮生成对话框,就会创建一个新的 QDialog 对象,并进行显示。如果点击很多次,就会产生很多个这样的对象,而且光是点击关闭对话框是没法进行内存释放的,所以很容易造成内存泄漏问题。
所以 Qt 给出了这样一个操作:当用户点击对话框关闭按钮的时候,触发 delete 操作。
dialog->setAttribute(Qt::WA_DeleteOnClose);
5.4 自定义对话框
创建一个 QMainWindow 项目后,点击新建文件,点击 Qt 设计器界面类
这里选择第三个
一直点击下一步,Qt 会为我们自动创建一个对话框界面
可以看到,项目里面多了一些对话框的文件,包括设计对话框的 ui 界面
进入 ui 界面,加入一些控件,并完成按钮的槽函数
#include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent) , ui(new Ui::Dialog) { ui->setupUi(this); } Dialog::~Dialog() { delete ui; } void Dialog::on_pushButton_clicked() { this->close(); }
回到 QMainWindow 的ui 界面,加入一个按钮,设计弹出对话框
#include "mainwindow.h" #include "ui_mainwindow.h" #include "dialog.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { Dialog* dialog = new Dialog(this); dialog->show(); dialog->setAttribute(Qt::WA_DeleteOnClose); }
注意这里包含的头文件不是 QDialog,而是我们自己的类,继承自 QDialog
5.5 模态对话框与非模态对话框
模态对话框指的是:显示后无法与父窗口进行交互,是一种阻塞式的对话框。使用QDialog::exec()函数调用。
模态对话框适用于必须依赖用户选择的场合,比如消息显示,文件选择,打印设置等。
非模态对话框显示后独立存在,可以同时与父窗口进行交互,是一种非阻塞式对话框,使用
QDialog:show()函数调用。
将上述代码的 show 函数改成 exec 函数,就是模态对话框。
运行程序,当窗口弹出后,无法操作父窗口
void MainWindow::on_pushButton_clicked() { Dialog* dialog = new Dialog(this); //dialog->show(); dialog->exec(); dialog->setAttribute(Qt::WA_DeleteOnClose); }
5.6 Qt 内置对话框
Qt提供了多种可复用的对话框类型,即Qt标准对话框。Qt 标准对话框全部继承于QDialog类。常用标准对话框如下:
5.6.1 消息对话框 QMessageBox
消息对话框是应用程序中最常用的界面元素。消息对话框主要用于为用户提示重要信息,强制用户进行选择操作。
QMessageBox类中定义了静态成员函数,可以直接调用创建不同风格的消息对话框,其中包括:
也可采用 setIcon 函数,输入对应的枚举类型,设置消息对话框类型
代码示例 : 警告类型对话框
在 ui 窗口上设置一个按钮,然后设置对应的槽函数
void MainWindow::on_pushButton_clicked() { // 创建 QMessageBox QMessageBox* messageBox = new QMessageBox(this); messageBox->setWindowTitle("对话框窗口标题"); messageBox->setText("这是对话框文本"); //设置对话框类型 messageBox->setIcon(QMessageBox::Warning); //在消息对话框上设置按钮 messageBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Save | QMessageBox::Cancel); messageBox->exec(); messageBox->setAttribute(Qt::WA_DeleteOnClose); }
其中设置对话框上的按钮,Qt 也已经枚举好了
运行程序,查看效果
代码示例:通过 exec 函数的返回值获得对话框被点击了哪个按钮
exec 函数是设定对话框是模态对话框,同时它也有一个返回值,返回值就是对话框被选中了哪个按钮的值。
void MainWindow::on_pushButton_clicked() { // 创建 QMessageBox QMessageBox* messageBox = new QMessageBox(this); messageBox->setWindowTitle("对话框窗口标题"); messageBox->setText("这是对话框文本"); //设置对话框类型 messageBox->setIcon(QMessageBox::Warning); //在消息对话框上设置按钮 messageBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Save | QMessageBox::Cancel); int result = messageBox->exec();//获取到返回值 if(result == QMessageBox::Ok) { qDebug() qDebug() qDebug() int result = QMessageBox::information(this,"对话框标题","对话框文本",QMessageBox::Ok | QMessageBox::Cancel); if(result == QMessageBox::Ok) { qDebug() qDebug() //这个函数静态函数,不必创建对话框对象就可直接使用 QColor color = QColorDialog::getColor(QColor(255,0,0),this,"选择颜色"); qDebug() QString filePath = QFileDialog::getOpenFileName(this); qDebug() QString filePath = QFileDialog::getSaveFileName(this); qDebug() bool ok = false;//点击对话框的ok,ok 被设为 true,点击cancel设为 false QFont font = QFontDialog::getFont(&ok); qDebug() int result = QInputDialog::getInt(this,"整数输入对话框","请输入一个整数: "); qDebug() QStringList items; items.push_back("1"); items.push_back("2"); items.push_back("3"); items.push_back("4"); QString item = QInputDialog::getItem(this,"条目输入对话框","请输入条目",items); qDebug()