QT搭建ArcGis_pro Office式界面————SARibbon的布局思路
目录
一、Ribbon是什么?
二、优秀的QT开源项目-SARibbon
1.项目链接
2.编译方法
三、使用方法
1.简单的层次示意
2. 拆分下的SARibbonBar层级关系
四、模仿搭建一个ArcGis_pro界面
1.创建Category和Pannel:
2.QAction 加入菜单
3.添加Gallery 预览控件
五、总结
前言
office式界面就是传说中的ribbon模式了,就是我们经常看到的word模式,office模式的tab和标题栏占用位置较多的一种界面模式。
如:word界面
WPS Ribbon 样式
一、Ribbon是什么?
Ribbon是现代化的方式帮助用户高效和直接的查找、理解和使用工具命令——通过最少的点击,减少从“尝试-错误”(trainl-and-error)方式中恢复操作,寻找新的操作的需要,并且不再需要区查看软件帮助。
Ribbon是一种命令工具条(command bar),将软件的功能集成到窗口上方的一系列标签(tabs)中。使用Ribbon可以使得软件的功能和特性更容易被用户发现,加快软件整体学习的速度,使用户能够根据他们自身的经验更好的控制整个程序。Ribbon可以代替传统的菜单栏和工具栏。
简单的理解,Ribbon是把菜单栏和工具栏合并了,并通过一个tab控件进行展示。
二、优秀的QT开源项目-SARibbon
1.项目链接
SARibbonBar
是Qt的开源Ribbon控件,代码托管于github和gitee
SARibbon
介绍[github],[gitee]SARibbon
布局入门[github],[gitee]
2.编译方法
使用Qt Creator直接打开SARibbon.pro,并编译即可,会编译出SARibbonBar库和一个(目前只有一个例子)例子,lib和例子的目录位于bin_qt{Qt版本}_{debug/release}_{32/64}目录下
在debug模式编译的库后面会加上d以作区别
可以把编译好的整个目录移动到需要的工程目录下,然后在项目的pro文件中,include SARibbonBar.pri即可,示例如下:
include($$PWD/SARibbonBar/SARibbon/SARibbonBar.pri)
三、使用方法
要使用SARibbon,需要对QMainWindow替换为SARibbonMainWindow,SARibbonMainWindow修改了QMainWindow对menubar的渲染
示例代码如下:
#include "SARibbonMainWindow.h"
class MainWindow : public SARibbonMainWindow
{Q_OBJECT
public:MainWindow(QWidget* par = nullptr);...
}
Ribbon是把菜单栏和工具栏合并了,并通过一个tab控件进行展示,SARibbon
在设计时参考了MFC Ribbon接口的命名风格,标签页称之为Category
(种类),每个Category
下面有多个pannel
(面板),面板下面才是具体的toolbutton。
1.简单的层次示意
2. 拆分下的SARibbonBar层级关系
看到这里,我们对它的构造层级就有了一定的了解,接下来我们再具体了解其中的各个控件
Ribbon标签(tabs)有许多“组”(group)构成,这些组中一些密切相关的功能的集合。出了标签和组,ribbons还包括:
- 一个应用程序按钮(Application Button),会弹出一个命令菜单,其中的命令会对整个文档或者工作空间做一些操作(笔者注:如保存,设置属性等),或者利用文档或者工作空间做一些事情(笔者注:如打印,发送邮件等),比如一些和文件相关的操作。
- 一个快捷工具栏(Quick Access Toolbar),是一个小的自定工具栏,显示常用的工具。
- 核心标签(Core tabs):总是会显示的标签面板。
- 上下文标签(Contextual tabs),只用当特定标签的对象被选中时才会显示。一直会显示的标签成为核心标签(Core tabs)
- 标签集(tab set)是针对某一特定标签的对象的标签面板的集合。因为对象可能属于不同个类型(例如一个表格中带有图片的的标题具有三个类别),可以有多个上下文标签组同时显示。
- 模态标签(Modal tabs),是一类特殊的核心标签,能够显示特定的临时模块,比如打印预览。
- 库按钮(Galleries),是以图形化显示的命令或者选项的列表。一个基于结果的库按钮显示了这个命令或者选项的会产生的效果,而不仅仅是命令本身。一个Ribbon内的库按钮(In-Ribbon gallery)是在Ribbon内的库按钮,代替弹出窗口的作用。
- 加强型提示(Enhanced Tooltips),简明的解释他们对应的命令的,并提示对应的快捷键。这些提示往往还带有响应的图形和帮助参考。加强型提示减少了使用功能帮助的可能性。
- 对话框加载按钮(Dialog Box Launcher),是一些在“组”下面的按钮,使用这些按钮,会弹出包含和功能组相关的特性的对话框。
- Category 类别,代表一个标签所呈现的内容,对应
SARibbonCategory
- Context Category 上下文类别,这个是一种特殊的类别,它正常不显示,需要基于上下文判断是否应该显示,最常用的就是word中插入图片后,会有图片修改相关的标签出现,如果没选中图片,这个标签就消失,这个就是上下文类别,对应
SARibbonContextCategory
- Pannel 面板,这个是一组菜单的集合,office里面板都会有个面板标题,显示在面板最下方,面板之后就是工具栏按钮(Action)
- Application Button 应用按钮,标签栏最左边的按钮(word就是对应文件按钮),这个按钮会触发一些特殊的页面或菜单,对应
SARibbonApplicationButton
,可以隐藏 - Quick Access Bar 快速响应栏,位于最顶部的一个简单工具栏,用于放置一些常用的action,对应
SARibbonQuickAccessBar
- Gallery 预览控件,这是Ribbon最吸引眼球的控件,用直观的图像把功能显示出来,甚至有些会根据上下文进行实时渲染,典型的就是word开始标签下的样式选择,对应
SARibbonGallery
四、模仿搭建一个ArcGis_pro界面
1.创建Category和Pannel:
//添加主标签页 - 通过addCategoryPage工厂函数添加SARibbonCategory* categoryMain = ribbon->addCategoryPage(tr("地图"));//使用addPannel函数来创建SARibbonPannel,效果和new SARibbonPannel再addPannel一样SARibbonPannel* pannelStyle = page->addPannel(("粘贴板"));QAction* actstickup = createAction(tr("粘贴"), ":/icon/icon/EditPaste32.png");pannelStyle->addLargeAction(actstickup);connect(actstickup, &QAction::triggered, this, [ this ](bool b) {Q_UNUSED(b);this->m_edit->append("actstickup clicked");});/** 新增剪贴* */QAction* clip = createAction(tr("剪贴"), ":/icon/icon/EditCut32.png", "剪贴");clip->setCheckable(true);pannelStyle->addSmallAction(clip);// 复制QAction* actShowHideButton = createAction(tr("复制"), ":/icon/icon/EditCopy32.png", "复制");actShowHideButton->setCheckable(true);pannelStyle->addSmallAction(actShowHideButton);connect(actShowHideButton, &QAction::triggered, this, [ this ](bool b) {this->ribbonBar()->showMinimumModeButton(b); //显示ribbon最小化按钮});actShowHideButton->trigger();//复制路径QAction* Paste = createAction(tr("复制路径"), ":/icon/icon/EffectsLayerDepthPriority16.png");Paste->setCheckable(true);Paste->setToolTip("复制路径");pannelStyle->addSmallAction(Paste);connect(Paste, &QAction::triggered, this, &MainWindow::onActionwordWrapIn2rowTriggered);
查看效果:
通过addLargeAction
、addMediumAction
、addSmallAction
可以组合出不同的布局样式。
代码体现:
QAction* actstickup = createAction(tr("粘贴"), ":/icon/icon/EditPaste32.png");pannelStyle->addLargeAction(actstickup);QAction* clip = createAction(tr("剪贴"), ":/icon/icon/EditCut32.png", "剪贴");clip->setCheckable(true);pannelStyle->addSmallAction(clip);
在标准的pannel中,一个action(按钮)有3种布局,以office word为例,pannel的三种布局其实是所占行数:
- 第一种,占满整个pannel,只有一行,称之为
large
- 第二种,一个pannel下放置两行,称之为
medium
- 第三种,一个pannel放置3行内容,称之为
samll
因此,pannel的布局其实归根结底就是行数,可以理解为QGridLayout
来对pannel进行布局的,把grid分割为6行,large
模式下占全部6行,medium
模式下占据3行,small
模式下占据2行(实际并不是用GridLayout布置的)。
枚举SARibbonPannelItem::RowProportion
是为了表征每个窗体在pannel所占行数的情况,在pannel布局中会常用到,这个枚举定义如下:
/*** @brief 定义了行的占比,ribbon中有large,media和small三种占比*/
enum RowProportion {None ///< 为定义占比,这时候将会依据expandingDirections来判断,如果能有Qt::Vertical,就等同于Large,否则就是Small, Large ///< 大占比,一个widget的高度会充满整个pannel, Medium ///< 中占比,在@ref SARibbonPannel::pannelLayoutMode 为 @ref SARibbonPannel::ThreeRowMode 时才会起作用,且要同一列里两个都是Medium时,会在三行中占据两行, Small ///< 小占比,占SARibbonPannel的一行,Medium在不满足条件时也会变为Small,但不会变为Large
};
SARibbonPannel里管理的每个action都会带有一个占位的属性(SARibbonPannelItem::RowProportion
),这个占位属性决定了这个action在pannel里的布局。
2.QAction 加入菜单
入浏览中添加:
"顶部图层" "可见图层 " "可选图层 " "内容中的可选内容 " "无弹出窗口 " "平面导航 " " 第一人称导航"
首先创建QAction 在创建menu 最后将menu设置到QAction中。代码如下:
SARibbonMenu *menuLook = new SARibbonMenu(this);QList<QString> list;list<<"顶部图层"<<"可见图层 "<<"可选图层 "<<"内容中的可选内容 "<<"无弹出窗口 "<<"平面导航 "<< " 第一人称导航";QAction* look = nullptr;{QIcon itemicon = QIcon(":/icon/icon/item.svg");for (int i =0;i<list.size();i++){look = menuLook->addAction(itemicon, tr("%1").arg(list[i]));look->setObjectName(QStringLiteral("item %1").arg(i+1));}}QAction* act = createAction(tr("浏览"), ":/icon/icon/3DNavigationTool32.png");act->setMenu(menuLook);btn = pannelToolButtonStyle->addLargeAction(act);btn->setPopupMode(QToolButton::InstantPopup);connect(act, &QAction::triggered, this, &MainWindow::onDelayedPopupCheckabletriggered);
查看效果:
我们可见其中menu 的图标都一样,不好区分,如果有朋友喜欢在做精致一点可以这样给每一个都加上不同的图标:或者加入分割符。
代码如下
QAction* Newreport = nullptr;{QList <QIcon> itemicon;//加入图标itemicon<<QIcon(":/icon/icon/item.svg")<<QIcon(":/icon/icon/aaa.svg")<<QIcon(":/icon/icon/bbb.svg");for (int i =0;i<listNewreport.size();i++){Newreport = menuNewreport->addAction(itemicon[i], tr("%1").arg(listNewreport[i]));//在第一行和第二行加一行分隔符。if(i == 1){menuConnection->addSeparator();}Newreport->setObjectName(QStringLiteral("item %1").arg(i+1));}}
3.添加Gallery 预览控件
如下图所示:
Gallery 预览控件,这是Ribbon最吸引眼球的控件,用直观的图像把功能显示出来,甚至有些会根据上下文进行实时渲染,典型的就是word开始标签下的样式选择,对应SARibbonGallery
对应代码设计:
SARibbonPannel* pannelLayerTemplates = page->addPannel(tr("图层模板"));SARibbonGallery* gallery = pannelLayerTemplates->addGallery();QList< QAction* > galleryActions;auto lambdaCreateGalleryAction = [ this ](const QString& text, const QString& iconurl) -> QAction* {QAction* act = this->createAction(text, iconurl);this->connect(act, &QAction::triggered, this, [ this, text ]() {if (this->m_edit) {this->m_edit->append(QString("%1 triggered").arg(text));}});return act;};galleryActions.append(lambdaCreateGalleryAction("亮色地图注释", ":/gallery-icon/icon/gallery/Document-File.svg"));galleryActions.append(lambdaCreateGalleryAction("深色地图注释", ":/gallery-icon/icon/gallery/Download-File.svg"));galleryActions.append(lambdaCreateGalleryAction("浅色地图注释", ":/gallery-icon/icon/gallery/Drive-File.svg"));galleryActions.append(lambdaCreateGalleryAction("配对地图注释", ":/gallery-icon/icon/gallery/Dropbox-File.svg"));galleryActions.append(lambdaCreateGalleryAction("粉彩地图注释", ":/gallery-icon/icon/gallery/Email-File.svg"));galleryActions.append(lambdaCreateGalleryAction("红绿地图注释", ":/gallery-icon/icon/gallery/Encode-File.svg"));
效果如下;
五、总结
总之 SARibbon是一个非常优秀的开源项目,更多更详细的例子参考项目官方文档:GitHub - czyt1988/SARibbon: Ribbon Control for Qt
本人也在学习中,如有错误欢迎指正。感谢您的阅读