目录
前言
office式界面就是传说中的ribbon模式了,就是我们经常看到的word模式,office模式的tab和标题栏占用位置较多的一种界面模式。
如:word界面
WPS Ribbon 样式
一、Ribbon是什么?
Ribbon是现代化的方式帮助用户高效和直接的查找、理解和使用工具命令——通过最少的点击,减少从“尝试-错误”(trainl-and-error)方式中恢复操作,寻找新的操作的需要,并且不再需要区查看软件帮助。
Ribbon是一种命令工具条(command bar),将软件的功能集成到窗口上方的一系列标签(tabs)中。使用Ribbon可以使得软件的功能和特性更容易被用户发现,加快软件整体学习的速度,使用户能够根据他们自身的经验更好的控制整个程序。Ribbon可以代替传统的菜单栏和工具栏。
简单的理解,Ribbon是把菜单栏和工具栏合并了,并通过一个tab控件进行展示。
二、优秀的QT开源项目-SARibbon
1.项目链接
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
本人也在学习中,如有错误欢迎指正。感谢您的阅读