C++客户端Qt开发——Qt窗口(菜单栏)

Qt窗口是通过QMainWindow类来实现的。

QMainWindow是一个为用户提供主窗口程序的类,继承自QWidget类,并且提供了一个预定义的布局。QMainWindow包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个浮动窗口(铆接部件)(dock widgets、一个状态栏(status bar)和一个中心部件(central widget),它是许多应用程序的基础,如文本编辑器,图片编辑器等。如下图为QMainwindow中各组件所处的位置:

1.菜单栏

Qt中的菜单栏是通过QMenuBar这个类来实现的。一个主窗口最多只有一个菜单栏。位于主窗口顶部、主窗口标题栏下面。

菜单栏中包含菜单,菜单中包含菜单项

菜单栏(QMenuBar)->菜单(QMenu)->菜单项(QAction)

新建项目的时候需要选择QMainWindowQWidget无法创建菜单栏

新建好的项目.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,这里的设置就是自己替换自己还是自己,仍然在对象树上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Outlier_9

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

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

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

打赏作者

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

抵扣说明:

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

余额充值