复用布局的菜单栏:layout()::menuBar() 2020/04/05
目录
引言
具体内容
效果
需要解决的问题
接口
遇到的问题
主要技术点
引言
最近几个月使用了H5的手机app开发工具HBuilder,越用越发现这个HBuilder非常好用,界面、功能各种细节很好,具体就是简单好用,没有任何多余的显示等,最大程度把屏幕大小利用起来了,这和我的软件理念符合,即功能一定要简洁、好用、不用学可以直接用。
自己的产品有个地方一直想改进下,就是标题栏和菜单栏合并,这几天专门把这个处理下,即自定义标题栏;用的Qt技术,Qt的理念很好,做这个不难,用了半天时间处理完,解决了很多细枝末节的问题;特此记录下整个思路和过程,及遇到的问题;
本文涉及的代码下载地址
具体内容
效果
实现如下的效果,即合并了标题栏、菜单栏,新的菜单栏包括图标、菜单栏、标题、三个按钮;
自定义的标题栏类基于QWidget,使用了布局、QLabel、QPushButton。如果想要其它界面效果,可以加入别的控件,很容易实现;
需要解决的问题
序号 | 问题 |
自定义菜单如何放到界面最上面 | |
自定义菜单中的菜单栏如何复用软件 的UI设计师菜单 | |
拖动自定义标题栏可以移动窗体 |
- 自定义QFrame
自定义QWidget,建立图标、菜单来自调用者、标题label、三个按钮,然后水平布局,实现一些事件响应、加入对外的调用接口,这样就可以了。
详细参见代码;直接看代码即可,不用逐行代码解释。
- 复用UI设计师的菜单栏
这里涉及Layout::addWidget后,相关的布局会自动把引用删除,不需要我们关心这个widget在哪个布局中。
- Layout()::setMenuBar()
调用主界面的layout()::setMenuBar()修改了主界面布局的菜单栏;
每个Layout布局都有一个最顶上的菜单栏、多个工具栏、多个item、多个QWidget,QLayout类得多掌握下。
接口
很多时候用UI设计师设计的界面,所以自定义的标题栏最好复用UI设计师的菜单栏;在ui->setupUi(this)前,前先创建MyWindowTitleBar;
其中myMenuBar是成员变量;
this->setWindowFlags(Qt::CustomizeWindowHint);
myMenuBar = new MyWindowTitleBar(this,":/images/icdTool.png");
installEventFilter(myMenuBar);
在ui->setupUi(this)之后,修改界面布局的MenuBar,即MenuBar的位置改为了自定义标题栏,其中包含了图标、菜单、标题、最小化最大化关闭三个按钮。
myMenuBar->SetMainMenuBar(ui->menuBar,":/images/icdTool.png");
this->layout()->setMenuBar(myMenuBar);
遇到的问题
- 复用MainWindow原有布局
已有软件基于UI设计师,想尽量少改动代码就可以改为自定义标题栏,如果修改UI,加入QWidget然后升级为MyMenuBar改动略大;
然后就想菜单栏的位置是最上面,如果菜单栏的位置换成自定义标题Widget不是很好,看自动生成的ui_mainwindow.h代码,有layout()::setMenuBar,感觉就是这个函数,可以替换成自己的Widget了,问题解决。不需要需改原有的ui文件了即可使用自定义标题栏。
去掉默认标题栏,没有了边框
查阅Assist需要设置Qt::FramelessWindowHint但是发现没有了边框,改为Qt::CustomizeWindowHint。
ShowMaximized实际全屏了
修改了WindowFlags后,最大化变成了全屏,没有找到解决方法,只好自定义了最大化和还原,改为计算QRect然后setGeometry。
ShowMaximize改为自定义接口
调用QWidget::showMaximized会导致全屏,改为调用 myMenuBar->OnMaxButton();
主要技术点
参考了一些资料,Qt的一些技术点见下表;
Qt就是这样有很多类,常用的、主要的就几个,掌握类的组织结构、脉络,掌握解决Qt问题的思路和方法很重要;方法就是发散思维分析可能的调用问题,然后F2跳到Qt类源码中分析、找可能的方法,然后Assist查找详细阅读分析;
序号 | 函数 | 作用 |
Qt类的子类化;自定义QFrame; |
| |
布局QLayout类的setMenuBar; |
| |
QObject的事件机制; |
| |
QWdiget的windowFlags、layout() |
| |
QObjiect::installEventFilter(myMenuBar); | 这个函数以前应该用过,记不清 拦截消息过滤到另一个对象的 | |
QObject::Sender() | 槽函数中,可以调用sender()获得发送这个信号的对象; | |
bool QObject::eventFilter(QObject *obj, QEvent *event);
| 事件过滤函数,可以过滤其它QWidget的事件,参见Assist有很多资料 | |
SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); | Windows api 拖动标题栏移动窗体的; |