Qt功能区:Ribbon使用
Ribbon使用
- 1. Ribbon功能区介绍
- 1.1 样式
- 2. 基本功能区设置
- 2.1 安装动态库(推荐)
- 2.2 在MainWindow中使用Ribbon
- 2.3 在QWidget中使用SARibbonBar
- 2.4 创建Category和Pannel
- 2.5 ContextCategory 上下文标签
- 创建
- 2.6 ApplicationButton
- 2.7 QuickAccessBar和rightButtonGroup
- 3. 样式设置
- 3.1SARibbonBar布局方案
- 对比
- 布局方式
- 窗口尺寸
- 实例
- 3.2 SARibbonBar文字换行,及图标大小
- 3.3 不同的“按钮”布局方式
- 3行或2行模式
1. Ribbon功能区介绍
Ribbon是把菜单栏和工具栏合并了,并通过一个tab控件进行展示,Ribbon是无法简单的使用Tab+Toolbar替代的,涉及到很多细节问题,SARibbon在设计时参考了MFC Ribbon接口的命名风格,标签页称之为Category(种类),每个Category下面有多个pannel(面板),面板下面管理着toolbutton,pannel有点类似传统的Toolbar,其层次结构如下图所示,这些命名参考了MFC的ribbon界面类。
- Category 类别,代表一个标签所呈现的内容,对应SARibbonCategory
- Context Category 上下文类别,这个是一种特殊的类别,它正常不显示,需要基于上下文判断是否应该显示,最常用的就是word中插入图片后,会有图片修改相关的标签出现,如果没选中图片,这个标签就消失,这个就是上下文类别,对应SARibbonContextCategory
- Pannel 面板,这个是一组菜单的集合,类似一个Toolbar,对应SARibbonPannel
- Application Button 应用按钮,标签栏最左边的按钮(word就是对应文件按钮),这个按钮会触发一些特殊的页面或菜单,对应SARibbonApplicationButton,可以隐藏
- Quick Access Bar 快速响应栏,位于最顶部的一个简单工具栏,用于放置一些常用的action,对应SARibbonQuickAccessBar
- Gallery 预览控件,这是Ribbon最吸引眼球的控件,用直观的图像把功能显示出来,甚至有些会根据上下文进行实时渲染,典型的就是word开始标签下的样式选择,对应SARibbonGallery
SARibbonBar的层次如下图所示:
1.1 样式
SARibbonBar::OfficeStyle Ribbon模式示例:
2. 基本功能区设置
2.1 安装动态库(推荐)
安装静态库中,将自身程序结构变得复杂,影响编写程序的整体性。
将动态库文件拷贝在项目的子文件夹中:
在项目中配置:
- 配置属性 → VC++目录 → 包含目录:头文件位置
- 链接器 → 常规 → 附加库目录:lib文件位置
- 链接器 → 输入 → 附加依赖项:.lib文件名称
部署动态库,将.dll复制到以下任一位置:
- 项目的运行程序目录下
- 系统PATH包含的目录
- 与可执行文件相同的目录
2.2 在MainWindow中使用Ribbon
操作步骤:
- 修改主窗口的父类
要MainWindow中使用SARibbon,需要把QMainWindow替换为SARibbonMainWindow,SARibbonMainWindow修改了QMainWindow对menubar的渲染方式。如下图所示:
//h文件中
#include "SARibbonMainWindow.h"
class QtMainWindowRibbon : public SARibbonMainWindow
{Q_OBJECTpublic:QtMainWindowRibbon(QWidget *parent = nullptr);~QtMainWindowRibbon();private:Ui::QtMainWindowRibbonClass *ui;
};//cpp文件中
QtMainWindowRibbon::QtMainWindowRibbon(QWidget *parent): SARibbonMainWindow(parent), ui(new Ui::QtMainWindowRibbonClass())
{ui->setupUi(this);
}
- 在Qt Designer中删除菜单栏
基本框架显示效果如下如所示:
2.3 在QWidget中使用SARibbonBar
SARibbonBar支持在QWidget上使用。在Dialog中使用,测试不可用。
#include "SARibbonWidget.h"class RibbonWidget : public SARibbonWidget
{Q_OBJECT
public:RibbonWidget(QWidget* parent = nullptr);
};
SARibbonWidget类提供了setWidget方法,可以嵌入任意的widget
RibbonWidget::RibbonWidget(QWidget* parent) : SARibbonWidget(parent)
{// 获取SARibbonBarSARibbonBar* ribbonbar = ribbonBar();// QWidget模式下,没有必要再显示标题ribbonbar->setTitleVisible(false);// QWidget模式下,直接使用紧凑模式效果更好ribbonbar->setRibbonStyle(SARibbonBar::RibbonStyleCompactThreeRow);// 取消applicationbuttonribbonbar->setApplicationButton(nullptr);
}
2.4 创建Category和Pannel
创建ribbon的顺序是:先创建类别(Category),再创建面板(Pannel),最后创建对应的toolbutton(action)
- 使用SARibbonBar::addCategoryPage把Category添加到SARibbonBar中;
- 使用SARibbonCategory::addPannel把Pannel添加到Category中;
- 使用SARibbonPannel::addAction可以在Pannel上添加action。
SARibbonBar *ribbon = ribbonBar();//添加主标签页 - 通过addCategoryPage工厂函数添加SARibbonCategory* categoryMain = ribbon->addCategoryPage(tr("Main"));//使用addPannel函数来创建SARibbonPannel,效果和new SARibbonPannel再addPannel一样SARibbonPannel* pannel1 = categoryMain->addPannel("Panel 1");QAction* actSave = new QAction(this);actSave->setText("save");actSave->setIcon(QIcon(":/File/save"));actSave->setObjectName("actSave"); // 为QObject 及其子类的对象设置一个唯一的名称,这个名称可以通过 objectName() 方法获取。//actSave->setShortcut(QKeySequence(QLatin1String("Ctrl+S")));actSave->setShortcut(QKeySequence(tr("Ctrl+S"))); //确保适应不用的语言,或者使用actSave->setShortcut(QKeySequence::Save);pannel1->addLargeAction(actSave);//信号槽connect(actSave, &QAction::triggered, this, [=]() {QMessageBox::about(this, "about", u8"保存文件!!!");});
Note:Ribbon的图标有大有小,通过addLargeAction、addMediumAction、addSmallAction可以组合出不同的布局样式
2.5 ContextCategory 上下文标签
所谓上下文标签是指在特殊情况下才出现的标签/标签组,例如office word在选中图片时会出现图片编辑的上下文标签,如下图所示:
- SARibbon中上下文标签对应的类为SARibbonContextCategory
创建
上下文标签一般在程序初始化的时候就创建好,平时隐藏,等待需要显示的时候再显示,创建上下文标签如下:
由于上下文标签需要使用时唤起,因此,用一个成员变量保存起来是一个比较好的选择,当然也可以遍历查找(SARibbonBar::contextCategoryList可以遍历所有的SARibbonContextCategory)
头文件:
SARibbonContextCategory* m_contextCategory;
CPP文件:
// 上下文标签SARibbonBar* ribbon = ribbonBar();mContextCategory = ribbon->addContextCategory(tr("context"), QColor(), 1);SARibbonCategory* contextCategoryPage1 = mContextCategory->addCategoryPage(tr("Page1"));createContextCategoryPage1(contextCategoryPage1);SARibbonCategory* contextCategoryPage2 = mContextCategory->addCategoryPage(tr("Page2"));createContextCategoryPage2(contextCategoryPage2);
由SARibbonContextCategory创建的SARibbonCategory归SARibbonContextCategory管理,只有SARibbonContextCategory“显示了”,其管理的SARibbonCategory才显示,注意: SARibbonContextCategory并不是一个窗口,所以,它的“显示”打了引号。
要显示一个上下文只需要调用SARibbonBar::showContextCategory/SARibbonBar::hideContextCategory即可:
void MainWindow::onShowContextCategory(bool on)
{if (on) {this->ribbonBar()->showContextCategory(m_contextCategory);} else {this->ribbonBar()->hideContextCategory(m_contextCategory);}
}
注意: 如果要删除contextCategory需要调用SARibbonBar::destroyContextCategory,而不是直接delete,调用SARibbonBar::destroyContextCategory之后无需再对ContextCategory的指针delete
this->ribbonBar()->destroyContextCategory(this->m_contextCategory);
2.6 ApplicationButton
ribbon界面左上角有个特殊且明显的按钮,称之为applicationButton,这个按钮一般用于调出菜单,SARibbonBar在构造时默认就创建了applicationButton,可以通过如下方式设置其文字:
SARibbonBar* ribbon = ribbonBar();if (!ribbon) {return;}QAbstractButton* btn = ribbon->applicationButton();if (!btn) {//! cn: SARibbonBar默认就会创建一个SARibbonApplicationButton,因此,在正常情况下,这个位置不会进入btn = new SARibbonApplicationButton(this);ribbon->setApplicationButton(btn);}btn->setText((" &File "));
默认的applicationButton继承自SARibbonApplicationButton,而SARibbonApplicationButton继承自QPushButton,因此你可以对其进行QPushButton所有的操作,如果想设置自己的Button作为applicationButton也是可以的,只需要调用SARibbonBar::setApplicationButton函数即可。
2.7 QuickAccessBar和rightButtonGroup
QuickAccessBar是左上角的快速工具栏,rightButtonGroup是右上角的快速工具栏,在office模式下分左右两边,在wps模式下,左右将合起来,统一放到右边。
SARibbon中:
- QuickAccessBar对应SARibbonQuickAccessBar类
- rightButtonGroup对应SARibbonButtonGroupWidget类
SARibbonBar在初始化时会默认创建QuickAccessBar和RightButtonGroup,通过SARibbonBar::quickAccessBar和SARibbonBar::rightButtonGroup即可获取其指针进行操作,示例如下:
// 创建QAction
QAction* QtMainWindowRibbon::createAction(const QString& text, const QString& iconurl, const QString& objName)
{QAction* act = new QAction(this);act->setText(text);act->setIcon(QIcon(iconurl));act->setObjectName(objName);return act;
}// 创建QuickAccess工具栏
void QtMainWindowRibbon::initQuickAccessBar()
{//获取功能区工具栏SARibbonBar* ribbon = ribbonBar();SARibbonQuickAccessBar* quickAccessBar = ribbon->quickAccessBar();quickAccessBar->addAction(createAction("save", ":/File/save", "save-quickbar"));quickAccessBar->addSeparator();quickAccessBar->addAction(createAction("undo", ":/File/undo", "undo"));quickAccessBar->addAction(createAction("redo", ":/File/redo", "redo"));quickAccessBar->addSeparator();
}// 创建RightButtonGruop
void QtMainWindowRibbon::initRightButtonGroup()
{//获取功能区工具栏SARibbonBar* ribbon = ribbonBar();SARibbonButtonGroupWidget* rightBar = ribbon->rightButtonGroup();QAction* actionHelp = createAction("help", ":/File/help", "help");connect(actionHelp, &QAction::triggered, this, [this]() {QMessageBox::information(this,tr("infomation"),tr("\n ===============""\n SARibbonBar version:%1""\n ===============").arg(SARibbonBar::versionString()));});rightBar->addAction(actionHelp);
}
3. 样式设置
3.1SARibbonBar布局方案
SARibbon支持4种ribbon布局方案,布局方案参考了office的ribbon风格和WPS的ribbon风格,布局方案的切换可 通过***void SARibbonBar::setRibbonStyle(RibbonStyle v)***实现。
office模式是最常见的ribbon模式,tab和标题栏占用位置较多,WPS设计的ribbon模式进行了改良,它为了减小ribbon的高度,把标签和标题栏设置在一起,这样减少了一个标题栏高度,有效利用了垂直空间,同时还把pannel的按钮布局由最大摆放3个变为摆放两个,进一步压缩了垂直空间。
对比
office的word界面和WPS Word界面截图对比
在正常屏幕下,WPS 样式会比 Office 样式减少至少30像素左右的垂直高度,相比1920*1080的屏幕来说,相当于节约了接近3%的垂直空间。
SARibbon中把带有标题栏的称之为宽松布局(Loose),宽松布局的各个元素如下图排列,这个布局和office的默认布局是一致的。
SARibbon中把带有标题栏和tab结合一起的布局方式称之为紧凑布局(Compact),紧凑布局的各个元素如下图排列:
布局方式
SARibbonBar提供了setRibbonStyle函数,可以定义当前的布局方案,枚举SARibbonBar::RibbonStyle定义了四种布局方案:
窗口尺寸
实例
SARibbonPannel* pannelStyle = categoryMain->addPannel(tr(u8"功能区样式设置"));//窗口功能区样式设置QButtonGroup* g = new QButtonGroup(categoryMain);QRadioButton* r = new QRadioButton();r->setText(tr("use office style"));r->setObjectName(("use office style"));r->setWindowTitle(r->text());r->setChecked(true);pannelStyle->addSmallWidget(r);g->addButton(r, SARibbonBar::RibbonStyleLooseThreeRow);r = new QRadioButton();r->setObjectName(("use wps style"));r->setText(tr("use wps style"));r->setWindowTitle(r->text());r->setChecked(false);pannelStyle->addSmallWidget(r);g->addButton(r, SARibbonBar::RibbonStyleCompactThreeRow);r = new QRadioButton();r->setObjectName(("use office 2row style"));r->setText(tr("use office 2 row style"));r->setWindowTitle(r->text());r->setChecked(false);pannelStyle->addSmallWidget(r);g->addButton(r, SARibbonBar::RibbonStyleLooseTwoRow);r = new QRadioButton();r->setObjectName(("use wps 2row style"));r->setText(tr("use wps 2row style"));r->setWindowTitle(r->text());r->setChecked(false);pannelStyle->addSmallWidget(r);g->addButton(r, SARibbonBar::RibbonStyleCompactTwoRow);connect(g, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::idClicked), this, &QtMainWindowRibbon::onStyleClicked);void QtMainWindowRibbon::onStyleClicked(int id)
{SARibbonBar::RibbonStyles ribbonStyle = static_cast<SARibbonBar::RibbonStyles>(id);ribbonBar()->setRibbonStyle(ribbonStyle);//mActionWordWrap->setChecked(SARibbonToolButton::isEnableWordWrap());
}
3.2 SARibbonBar文字换行,及图标大小
通过SARibbonBar::setEnableWordWrap函数可以控制SARibbonBar的文字是否换行,SARibbonBar的高度是固定的,文字是否换行会影响图标显示的大小,因此,如果你想图标看起来更大,可以设置文字不换行。
在SARibbonBar::RibbonStyleCompactTwoRow的布局模式下,文字不换行的显示效果如下:
SARibbonBar文字设置为不换行后,会使图标的显示空间变得更大。
SARibbonPannel* pannelStyle = categoryMain->addPannel(tr(u8"功能区样式设置"));//设置功能区图标换行操作QAction * actWordWrap = createAction(tr(u8"名称换行"), ":/File/wordWrap","wordWarp");actWordWrap->setCheckable(ribbonBar()->isEnableWordWrap());pannelStyle->addLargeAction(actWordWrap);connect(actWordWrap, &QAction::triggered, this, [this](bool b) {this->ribbonBar()->setEnableWordWrap(b);});
3.3 不同的“按钮”布局方式
SARibbonPannel提供了三个添加action的方法:
- addLargeAction
- addMediumAction
- addSmallAction
在标准的pannel中,一个action(按钮)有3种布局,以office word为例,pannel的三种布局其实是所占行数:
第一种,占满整个pannel,称之为large
第二种,一个pannel下可以放置2个按钮,称之为medium
第三种,一个pannel放置3个按钮,称之为samll
3行或2行模式
枚举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里的布局