Qt窗口是通过QMainWindow
类来实现的。
QMainWindow
是一个为用户提供主窗口程序的类,继承自QWidget类,并且提供了一个预定义的布局。QMainWindow
包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个浮动窗口(铆接部件)(dock widgets、一个状态栏(status bar)和一个中心部件(central widget),它是许多应用程序的基础,如文本编辑器,图片编辑器等。如下图为QMainwindow中各组件所处的位置:
1.菜单栏
Qt中的菜单栏是通过QMenuBar
这个类来实现的。一个主窗口最多只有一个菜单栏。位于主窗口顶部、主窗口标题栏下面。
菜单栏中包含菜单,菜单中包含菜单项
菜单栏(QMenuBar)->菜单(QMenu)->菜单项(QAction)
新建项目的时候需要选择QMainWindow
,QWidget
无法创建菜单栏
新建好的项目.ui
文件会有些不一样
①设置菜单栏及菜单和菜单项
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//先创建一个菜单栏
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("新建");
QAction* action2 = new QAction("打开");
QAction* action3 = new QAction("保存");
QAction* action4 = new QAction("另存为");
QAction* action5 = new QAction("退出");
menu1->addAction(action1);
menu1->addAction(action2);
menu1->addAction(action3);
menu1->addAction(action4);
menu1->addAction(action5);
//绑定槽函数
connect(action1,&QAction::triggered,this,&MainWindow::handle);
connect(action5,&QAction::triggered,this,&MainWindow::close);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::handle()
{
qDebug() << "触发新建操作";
}
void MainWindow::close()
{
qDebug() << "触发退出操作";
}
②给菜单栏设置快捷键
在创建QMenu对象的时候,命名改菜单时直接加上(&+字母)就可以设置快捷键效果了(Alt+该字母)
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenuBar* menubar = new QMenuBar();
this->setMenuBar(menubar);
QMenu* menu1 = new QMenu("文件(&F)");
QMenu* menu2 = new QMenu("编辑(&V)");
QMenu* menu3 = new QMenu("视图(&E)");
QMenu* menu4 = new QMenu("关于(&A)");
menubar->addMenu(menu1);
menubar->addMenu(menu2);
menubar->addMenu(menu3);
menubar->addMenu(menu4);
QAction* action1 = new QAction("菜单项1");
QAction* action2 = new QAction("菜单项2");
QAction* action3 = new QAction("菜单项3");
QAction* action4 = new QAction("菜单项4");
menu1->addAction(action1);
menu2->addAction(action2);
menu3->addAction(action3);
menu4->addAction(action4);
}
MainWindow::~MainWindow()
{
delete ui;
}
③给菜单项设置快捷键
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenuBar* menubar = new QMenuBar();
this->setMenuBar(menubar);
QMenu* menu1 = new QMenu("文件(&F)");
QMenu* menu2 = new QMenu("编辑(&V)");
menubar->addMenu(menu1);
menubar->addMenu(menu2);
//需要用connect绑定槽函数
QAction* action1 = new QAction("菜单项1(&Q)");
QAction* action2 = new QAction("菜单项2(&W)");
QAction* action3 = new QAction("菜单项3(&E)");
QAction* action4 = new QAction("菜单项4(&R)");
menu1->addAction(action1);
menu1->addAction(action2);
menu2->addAction(action3);
menu2->addAction(action4);
connect(action1,&QAction::triggered,this,&MainWindow::handle1);
connect(action2,&QAction::triggered,this,&MainWindow::handle2);
connect(action3,&QAction::triggered,this,&MainWindow::handle3);
connect(action4,&QAction::triggered,this,&MainWindow::handle4);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::handle1()
{
qDebug() << "handle1";
}
void MainWindow::handle2()
{
qDebug() << "handle2";
}
void MainWindow::handle3()
{
qDebug() << "handle3";
}
void MainWindow::handle4()
{
qDebug() << "handle4";
}
④给菜单项添加子菜单
加分界线
menu->addAction(action1);
menu->addSeparator();
menu->addAction(action2);
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenuBar* menubar = new QMenuBar();
this->setMenuBar(menubar);
QMenu* menuParent = new QMenu("父菜单");
QMenu* menuChild = new QMenu("子菜单");
menubar->addMenu(menuParent);
menuParent->addMenu(menuChild);
QAction* action1 = new QAction("菜单项1");
QAction* action2 = new QAction("菜单项2");
QAction* action3 = new QAction("菜单项3");
QAction* action4 = new QAction("菜单项4");
menuChild->addAction(action1);
menuChild->addAction(action2);
menuChild->addAction(action3);
menuChild->addAction(action4);
}
MainWindow::~MainWindow()
{
delete ui;
}
⑤添加图标
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// QMenuBar* menubar = new QMenuBar();
// this->setMenuBar(menubar);
//这种创建方式更合适,如果已存在创建好的menubar就返回,如果不存在就新创建
//如果是获取到已经存在的QMenuBar,这里的设置就是自己替换自己还是自己,仍然在对象树上
QMenuBar* menubar = this->menuBar();
this->setMenuBar(menubar);
QMenu* menu = new QMenu("菜单");
menubar->addMenu(menu);
QAction* action1 = new QAction("菜单项1");
action1->setIcon(QIcon(":/1.jpg"));
QAction* action2 = new QAction("菜单项2");
action2->setIcon(QIcon(":/2.jpg"));
menu->addAction(action1);
menu->addAction(action2);
}
MainWindow::~MainWindow()
{
delete ui;
}
QMenuBar的创建方式
如果在新建文件时,选择了自动构建.ui
文件,这样的创建方式会导致内存泄漏,因为Qt Creator已经给创建好了一个menubar,在.ui
文件的对象树中可以看到
当设置新的QMenuBar进来的时候,就会导致旧的QMenuBar脱离了Qt的对象树了,意味着后续就无法对这个对象进行释放了
上述程序如果窗口关闭,对象树释放,此时进程也就结束了.进程结束,自然所有内存都回收给系统,上述内存泄露也不会造成影响,
但是如果这样的代码是出现在一个多窗口的程序中,如果涉及到窗口的频繁跳转切换(窗口的频繁创建销毁),上述内存泄露就会更严重一些
解决方式:QMenuBar* menubar = this->menuBar();
this->setMenuBar(menubar);
这种创建方式更合适,如果已存在创建好的menubar就返回,如果不存在就新创建
如果是获取到已经存在的QMenuBar,这里的设置就是自己替换自己还是自己,仍然在对象树上