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里的布局