news 2026/6/5 18:48:51

QT——QMainWindow

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
QT——QMainWindow

目录

QMainWindow

菜单栏(Menu Bar)

添加菜单栏,添加菜单,添加菜单项,并为菜单项设置触发事件(槽函数)

给菜单,菜单项添加快捷键

添加子菜单

给菜单项之间添加分割线

给菜单/菜单项添加图标

题外话——创建菜单栏的内存泄漏

工具栏(QToolBar)

创建工具栏,给工具栏添加action,给action设置图标以及提示信息

菜单栏和工具栏结合使用

设置多个工具栏

工具栏的移动设置

状态栏(Status Bar)

QDockWidget


QMainWindow

大多数时候客户端窗口的主体是QMainWindow而不是QWidget,QWidget是其中的组成部分。QMainWindow的组成如下:

实际上,当我们创建一个QMainWindow项目并选择生成ui文件的时候,中心窗口,菜单栏,状态栏都是默认创建好的:


菜单栏(Menu Bar)

一个窗口只能有一个菜单栏,菜单栏结构示意图如下:

添加菜单栏,添加菜单,添加菜单项,并为菜单项设置触发事件(槽函数)

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建一个菜单栏对象 QMenuBar* menubar = new QMenuBar(); //将菜单栏添加到窗口,此时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 * action1 = new QAction("打开");//创建菜单项对象 QAction * action2 = new QAction("保存"); QAction * action3 = new QAction("退出"); menu1->addAction(action1);//把菜单项对象添加到菜单 menu1->addAction(action2); menu1->addAction(action3); //给菜单项关联一个槽 connect(action1,&QAction::triggered,this,&MainWindow::handler); } void MainWindow::handler() { qDebug()<<"点击了打开按钮!"; }

给菜单,菜单项添加快捷键

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建一个菜单栏对象 QMenuBar* menubar = new QMenuBar(); //将菜单栏添加到窗口,此时menubar的父节点被设置为窗口 this->setMenuBar(menubar); //给菜单栏添加菜单 QMenu *menu1 = new QMenu("文件(&a)");//创建菜单对象,并添加快捷键ALt+a QMenu *menu2 = new QMenu("编辑(&b)"); QMenu *menu3 = new QMenu("帮助(&c)"); menubar->addMenu(menu1);//把菜单对象添加到菜单栏 menubar->addMenu(menu2); menubar->addMenu(menu3); //给菜单添加菜单项 QAction * action1 = new QAction("打开(&z)");//创建菜单项对象并添加快捷键ALt+z QAction * action2 = new QAction("保存"); QAction * action3 = new QAction("退出"); menu1->addAction(action1);//把菜单项对象添加到菜单 menu1->addAction(action2); menu1->addAction(action3); //给菜单项关联一个槽 connect(action1,&QAction::triggered,this,&MainWindow::handler); }

在菜单/菜单项文本添加"&+字母"就表示给这个菜单/菜单项添加快捷键"alt+字母"

添加子菜单

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建一个菜单栏对象 QMenuBar* menubar = new QMenuBar(); //将菜单栏添加到窗口,此时menubar的父节点被设置为窗口 this->setMenuBar(menubar); //给菜单栏添加菜单 QMenu *menu1 = new QMenu("父菜单");//创建菜单对象 QMenu *menu2 = new QMenu("菜单2"); QMenu *menu3 = new QMenu("子菜单"); menubar->addMenu(menu1);//把菜单对象添加到菜单栏 menubar->addMenu(menu2); menu1->addMenu(menu3);//菜单对象中也有addMenu方法,用于添加子菜单 //给菜单添加菜单项 QAction * action1 = new QAction("打开");//创建菜单项对象 QAction * action2 = new QAction("保存"); QAction * action3 = new QAction("退出"); menu1->addAction(action1);//把菜单项对象添加到菜单 menu3->addAction(action2); menu3->addAction(action3); }

给菜单项之间添加分割线

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建一个菜单栏对象 QMenuBar* menubar = new QMenuBar(); //将菜单栏添加到窗口,此时menubar的父节点被设置为窗口 this->setMenuBar(menubar); //给菜单栏添加菜单 QMenu *menu1 = new QMenu("菜单1");//创建菜单对象 QMenu *menu2 = new QMenu("菜单2"); menubar->addMenu(menu1);//把菜单对象添加到菜单栏 menubar->addMenu(menu2); //给菜单添加菜单项 QAction * action1 = new QAction("菜单项1");//创建菜单项对象 QAction * action2 = new QAction("菜单项2"); QAction * action3 = new QAction("菜单项3"); QAction * action4 = new QAction("菜单项4"); menu1->addAction(action1);//把菜单项对象添加到菜单 menu1->addAction(action2); menu1->addSeparator();//把分割线也当做一个菜单项,它在谁后面被添加,分割线就在谁后面 menu1->addAction(action3); menu1->addAction(action4); }

给菜单/菜单项添加图标

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建一个菜单栏对象 QMenuBar* menubar = new QMenuBar(); //将菜单栏添加到窗口,此时menubar的父节点被设置为窗口 this->setMenuBar(menubar); //给菜单栏添加菜单 QMenu *menu1 = new QMenu("菜单1");//创建菜单对象 QMenu *menu2 = new QMenu("子菜单");//创建菜单对象 menubar->addMenu(menu1);//把菜单对象添加到菜单栏 menu1->addMenu(menu2);//给菜单1添加子菜单 //给菜单1添加图标 menu1->setIcon(QIcon(":/rose.jpg")); //给子菜单添加图标 menu2->setIcon(QIcon(":/rose.jpg")); //给菜单添加菜单项 QAction * action1 = new QAction("菜单项1");//创建菜单项对象 //给菜单项添加图标 action1->setIcon(QIcon(":/rose.jpg")); //把菜单项对象添加到菜单 menu1->addAction(action1); }

菜单,子菜单,菜单项都可以设置图标,但是如果给菜单设置图标的话,就会把原有文本覆盖

题外话——创建菜单栏的内存泄漏

在该文章开头我们以及谈及,一旦创建了一个QMainWindows项目并且选择使用QtDesigner(也就是使用ui文件),那么默认就会生成一个菜单栏,而上面的所有代码中我是这么写的:

//创建一个菜单栏对象 QMenuBar* menubar = new QMenuBar(); //将菜单栏添加到窗口,此时menubar的父节点被设置为窗口 this->setMenuBar(menubar);

一个窗口只能有一个菜单栏,这就相当于我们新创建了一个菜单栏,把人家默认生成的给替换掉了,原有的菜单栏对象就得不到释放了。(细心的同学可能发现我在创建菜单栏的时候没有指定菜单栏的父对象可能导致内存泄漏,不必担心,setMenuBar会帮我们把对象挂到对象树上。)下面我们修改代码,修复内存泄漏:

QMenuBar* menubar = this->menuBar(); this->setMenuBar(menubar);

menuBar函数就是从窗口中获取一个菜单栏对象,如果有就直接获取,如果没有就创建一个。这样一来,在下面设置窗口的菜单栏时,如果本来没有,我们就把新创建的菜单栏对象设置进去了,如果有,也是自己替换自己,不会造成内存泄漏。

当然,不只是菜单栏,选择ui文件后默认生成的栏如果使用不当都会出现这种问题。


工具栏(QToolBar)

大多数情况下,工具栏中的内容就是菜单中的菜单项,相当于菜单项的快捷键,因此工具栏中的元素也是用QAction对象表示

除此之外,一个窗口可以有多个工具栏,也正是因此,添加工具栏的接口是addToolBar而不是像添加菜单栏一样格式的setToolBar。

建工具栏,给工具栏添加action,给action设置图标以及提示信息

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建工具栏对象 QToolBar* tb = new QToolBar(); //将工具栏对象添加到窗口中 this->addToolBar(tb); //创建QAction QAction * action1 = new QAction("选项1"); QAction * action2 = new QAction("选项2"); //给QAction设置图标,一般来说工具栏的元素都用图标表示 action1->setIcon(QIcon(":/rose.jpg")); action2->setIcon(QIcon(":/rose.jpg")); //给工具栏上的元素设置图标会导致文本被覆盖,因此可以给每个元素设置一个提示信息,鼠标悬停到对应元素就显示提示信息 //实际上就算不设置提示信息,也有默认的提示信息,即action原来的文本 action1->setToolTip("这是选项1"); action2->setToolTip("这是选项2"); //把QAction对象添加到工具栏中 tb->addAction(action1); tb->addAction(action2); }

菜单栏和工具栏结合使用

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //创建工具栏对象 QToolBar* tb = new QToolBar(); this->addToolBar(tb); //添加菜单栏对象 QMenuBar* mb = this->menuBar(); this->setMenuBar(mb); //创建QAction QAction * action1 = new QAction("选项1"); QAction * action2 = new QAction("选项2"); //把QAction对象添加到工具栏中 tb->addAction(action1); tb->addAction(action2); //把QAction对象添加到菜单栏中 mb->addAction(action1); mb->addAction(action2); }

同一个action元素被菜单栏和工具栏同时包含,那么会不会导致对象树上一个节点有两个父节点?或者一个节点释放两次呢?不会的,Qt帮我们处理好了。

设置多个工具栏

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //添加工具栏对象 QToolBar* tb = new QToolBar(); this->addToolBar(tb); QToolBar* tb2 = new QToolBar(); this->addToolBar(tb); //创建QAction QAction * action1 = new QAction("选项1"); QAction * action2 = new QAction("选项2"); //把QAction对象添加到工具栏中 tb->addAction(action1); tb->addAction(action2); tb2->addAction(action1); tb2->addAction(action2); }

工具栏的移动设置

默认情况下可以将工具栏拖动到上下左右四个方向并停靠在窗口边沿,以及浮动在窗口内部

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //添加工具栏对象 QToolBar* tb = new QToolBar(); this->addToolBar(Qt::LeftToolBarArea,tb);//在添加工具栏的时候可以设置工具栏的初始位置 //创建QAction QAction * action1 = new QAction("选项1"); QAction * action2 = new QAction("选项2"); //把QAction对象添加到工具栏中 tb->addAction(action1); tb->addAction(action2); //设置工具栏只允许在左边和右边停靠以及浮动 tb->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea); //设置工具栏不允许浮动 tb->setFloatable(false); //设置工具栏不允许移动, 固定住了 tb->setMovable(false); }


状态栏(Status Bar)

状态栏也是勾选ui文件后默认生成的,设置状态栏的时候要注意内存泄漏。

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //添加状态栏对象 QStatusBar * sb = this->statusBar(); this->setStatusBar(sb); //直接让状态栏展示文本,可以timeout,到期自动不在显示文本,如果timeout为0表示一直展示 //sb->showMessage("这是一个状态消息",1000); //给状态栏添加标签控件,可以在添加的时候设置拉升系数 QLabel* label1 = new QLabel("哈哈哈"); sb->addWidget(label1,1); QLabel* label2 = new QLabel("嘿嘿嘿"); sb->addWidget(label2,2); //给状态栏添加按钮控件,这次我们从右往左添加 QPushButton* button = new QPushButton("按钮"); sb->addPermanentWidget(button);//调用这个函数就表示从右往左添加 //给状态栏添加进度条 QProgressBar* p = new QProgressBar(); p->setRange(0,100); p->setValue(50); sb->addWidget(p); }

QDockWidget

QDockWidget是一个浮动窗口控件,相当于独立的新窗口。不过需要注意的是,QDockWidget默认只能添加一个控件,因此如果想要在浮动窗口上设置更多样式需要先创建一个QWidget并把控件设置其中,然后只要把QWidget对象设置到QDockWidget中去即可

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //添加一个浮动窗口对象 QDockWidget* widget = new QDockWidget(); this->addDockWidget(Qt::LeftDockWidgetArea,widget);//添加的时候要指定新窗口的初始停靠位置 //给浮动窗口设置窗口标题 widget->setWindowTitle("浮动窗口"); //创建一个窗口对象 QWidget* qwidget = new QWidget(); //把QWidget对象设置进浮动窗口去 widget->setWidget(qwidget); //然后我们就可以在Qwidget中添加更多控件了 //创建一个布局管理器并添加到QWidget中去 QVBoxLayout* layout = new QVBoxLayout(); qwidget->setLayout(layout); //在布局管理器中添加控件 layout->addWidget(new QLabel("这是一个标签")); layout->addWidget(new QPushButton("按钮")); //还可以给浮动窗口设置什么位置可以停靠 widget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::TopDockWidgetArea); }


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/2 11:43:44

互联网大厂Java求职面试实战:多技术栈与业务场景深度解析

互联网大厂Java求职面试实战&#xff1a;多技术栈与业务场景深度解析 本文通过一个企业协同与SaaS场景的面试故事&#xff0c;真实展现互联网大厂Java求职者谢飞机与严肃面试官的问答过程&#xff0c;涵盖Java SE、Spring Boot、微服务、数据库、缓存、消息队列、安全框架、AI等…

作者头像 李华
网站建设 2026/5/31 4:39:43

从 .env 到动态配置:前端工程的一次升级

点击上方 程序员成长指北&#xff0c;关注公众号 回复1&#xff0c;加入高级Node交流群 前言 很多前端和 Node.js 项目&#xff0c;配置管理几乎都是从环境变量开始的&#xff1a;.env、process.env、再配合一次部署。但当你需要临时关掉一个功能、调整接口限流、做灰度发布时&…

作者头像 李华
网站建设 2026/5/30 20:17:35

军工装备管理系统TinyMCE4导入PDF图纸出现字体缺失怎么办?

项目需求技术评估与实施方案 一、需求背景分析 作为北京某国企项目负责人&#xff0c;我们当前面临在企业网站后台管理系统中集成Word粘贴、文档导入和微信公众号内容处理功能的迫切需求。该需求源于政府项目对文档处理能力提升的要求&#xff0c;同时需要满足信创国产化环境…

作者头像 李华
网站建设 2026/6/5 8:46:21

告别杂乱!NAS 装个 Sun-Panel+cpolar,数据管理居然能这么省心

Sun-Panel 是一款主打可视化整合的私有云管理工具&#xff0c;核心功能是把 NAS、服务器、常用工具的访问入口收拢到统一面板&#xff0c;支持多账号权限隔离&#xff0c;还能自定义界面样式&#xff0c;适配 Windows、macOS、Linux 等多系统&#xff0c;甚至树莓派也能流畅运行…

作者头像 李华
网站建设 2026/5/21 10:39:08

互联网大厂Java面试:严肃面试官与搞笑程序员的对决222

场景&#xff1a; 在某互联网大厂的面试室&#xff0c;一位严肃的面试官正准备提问&#xff0c;而对面坐着一位看似紧张却又想显得轻松的程序员小张。 面试官&#xff1a;我们先来聊聊Java核心知识。第一个问题&#xff0c;Java中的JVM是如何管理内存的&#xff1f; 程序员小张…

作者头像 李华
网站建设 2026/6/3 22:25:44

深度测评 9个AI论文工具:本科生毕业论文写作全攻略

随着AI技术的不断进步&#xff0c;越来越多的学术写作工具被推向市场&#xff0c;为本科生撰写毕业论文提供了新的解决方案。然而&#xff0c;面对种类繁多的AI工具&#xff0c;如何选择真正适合自己需求的产品成为一大难题。为此&#xff0c;我们基于2026年的实测数据与用户反…

作者头像 李华