开源地址:https://github.com/SeriousAlexej/TabToolbar
该库的使用方式有两种:
- 使用json配置文件配置TabToolBar
- 使用代码构建TabToolBar
编译
项目是使用Qt和CMake管理的,并且在开发的时候使用的是Qt6,我实测通过更改CMake的配置文件,在Qt6中也是可以使用的。这一部分修改省略
- 最后运行起来的情况
这里我主要想探索一下,这个开源库的使用
一、探索
(一)、学习他的案例程序
在文件结构中的位置如上图。
使用方式一:使用json配置文件
tt::Builder ttb(this);
ttb.SetCustomWidgetCreator("textEdit", []() { return new QTextEdit(); });
ttb.SetCustomWidgetCreator("checkBox", []() { return new QCheckBox(); });
ttb.SetCustomWidgetCreator("pushButton", []() { return new QPushButton(); });
tt::TabToolbar* tabToolbar = ttb.CreateTabToolbar(":/tt/tabtoolbar.json");
addToolBar(Qt::TopToolBarArea, tabToolbar);
ttb["customTextEdit"]->setMaximumWidth(100);
((QCheckBox*)ttb["customCheckBox"])->setText("点击");
QPushButton* btn = (QPushButton*)ttb["customEditButton"];
btn->setText("Edit");
static bool kek = true;
tt::Page* editPage = (tt::Page*)ttb["Edit"];
QObject::connect(btn, &QPushButton::clicked, [editPage]()
{
if(kek)
editPage->hide();
else
editPage->show();
kek = !kek;
});
QObject::connect(tabToolbar, &tt::TabToolbar::SpecialTabClicked, this, [this]()
{
QMessageBox::information(this, "Kek", "Cheburek");
});
//create buttons for each style
tt::Group* stylesGroup = (tt::Group*)ttb["Styles"];
stylesGroup->AddSeparator();
QStringList styles = tt::GetRegisteredStyles();
for(int i=0; i<styles.size(); i++)
{
const QString styleName = styles.at(i);
QPushButton* btn = new QPushButton(styleName, this);
QObject::connect(btn, &QPushButton::clicked, [styleName, tabToolbar]() { tabToolbar->SetStyle(styleName); });
stylesGroup->AddWidget(btn);
}
tt::RegisterStyle("NoStyle", []()
{
tt::StyleParams* params = new tt::StyleParams();
params->UseTemplateSheet = false;
params->AdditionalStyleSheet = "";
return params;
});
btn = (QPushButton*)ttb["nativeStyleButton"];
btn->setText("No Style");
QObject::connect(btn, &QPushButton::clicked, [tabToolbar]() { tabToolbar->SetStyle("NoStyle"); });
btn = (QPushButton*)ttb["defaultStyleButton"];
btn->setText("Default");
QObject::connect(btn, &QPushButton::clicked, [tabToolbar]() { tabToolbar->SetStyle(tt::GetDefaultStyle()); });
{
"groupHeight": 75,
"groupRowCount": 3,
"specialTab": true,
"cornerActions": [
"actionHelp"
],
"menus": [
{
"name": "dummyMenu",
"actions": [
"actionDummy",
"separator",
"actionHelp"
]
}
],
"tabs": [
{
"displayName": "文件",
"name": "File",
"groups": []
},
{
"displayName": "编辑",
"name": "Edit",
"groups": [
{
"displayName": "样式",
"name": "Styles",
"content": [
{
"itemType": "subgroup",
"aligned": true,
"name": "stylesSubgroup1",
"content": [
{
"itemType": "pushButton",
"name": "nativeStyleButton"
},
{
"itemType": "pushButton",
"name": "defaultStyleButton"
}
]
}
]
}
]
},
{
"displayName": "视图",
"name": "View",
"groups": [
{
"displayName": "分组1",
"name": "Group 1",
"content": [
{
"itemType": "action",
"type": "delayedPopup",
"name": "actionOpen"
},
{
"itemType": "separator"
},
{
"itemType": "action",
"type": "delayedPopup",
"name": "actionSave"
},
{
"itemType": "action",
"type": "delayedPopup",
"name": "actionSaveAs"
}
]
},
{
"displayName": "分组2",
"name": "Group 2",
"content": [
{
"itemType": "action",
"type": "instantPopup",
"name": "actionPolypaint",
"menu": "dummyMenu"
},
{
"itemType": "action",
"type": "instantPopup",
"name": "actionScale",
"menu": "dummyMenu"
},
{
"itemType": "separator"
},
{
"itemType": "textEdit",
"name": "customTextEdit"
},
{
"itemType": "subgroup",
"name": "group2Subgroup",
"aligned": true,
"content": [
{
"itemType": "action",
"type": "delayedPopup",
"name": "actionUndo"
},
{
"itemType": "action",
"type": "delayedPopup",
"name": "actionRedo"
},
{
"itemType": "action",
"type": "instantPopup",
"name": "actionClose",
"menu": "dummyMenu"
}
]
}
]
},
{
"displayName": "分组3",
"name": "Group 3",
"content": [
{
"itemType": "action",
"type": "menuButtonPopup",
"name": "actionSettings",
"menu": "dummyMenu"
},
{
"itemType": "subgroup",
"name": "group3Subgroup1",
"aligned": true,
"content": [
{
"itemType": "horizontalActions",
"actions": [
{
"type": "delayedPopup",
"name": "actionSave"
},
{
"type": "instantPopup",
"name": "actionPolypaint",
"menu": "dummyMenu"
},
{
"type": "menuButtonPopup",
"name": "actionSettings",
"menu": "dummyMenu"
}
]
},
{
"itemType": "horizontalActions",
"actions": [
{
"type": "delayedPopup",
"name": "actionUndo"
},
{
"type": "delayedPopup",
"name": "actionRedo"
},
{
"type": "instantPopup",
"name": "actionClose",
"menu": "dummyMenu"
}
]
},
{
"itemType": "checkBox",
"name": "customCheckBox"
}
]
},
{
"itemType": "separator"
},
{
"itemType": "subgroup",
"name": "group3Subgroup2",
"aligned": false,
"content": [
{
"itemType": "pushButton",
"name": "customEditButton"
},
{
"itemType": "action",
"type": "delayedPopup",
"name": "actionSaveAs"
}
]
}
]
}
]
},
{
"displayName": "帮助",
"name": "Help",
"groups": [
{
"displayName": "",
"name": "HelpGroup",
"content": [
{
"displayName": "帮助",
"itemType": "action",
"type": "delayedPopup",
"name": "actionHelp"
},
{
"itemType": "action",
"type": "delayedPopup",
"name": "actionAbout"
}
]
}
]
}
]
}
分析一下
1.创建对象
tt::Builder ttb(this);
ttb.SetCustomWidgetCreator("textEdit", []() { return new QTextEdit(); });
ttb.SetCustomWidgetCreator("checkBox", []() { return new QCheckBox(); });
ttb.SetCustomWidgetCreator("pushButton", []() { return new QPushButton(); });
- 创建Tabtoolbar并添加到tool工具栏
tt::TabToolbar* tabToolbar = ttb.CreateTabToolbar(":/tt/tabtoolbar.json");
addToolBar(Qt::TopToolBarArea, tabToolbar);
ttb["customTextEdit"]->setMaximumWidth(100);
((QCheckBox*)ttb["customCheckBox"])->setText("点击");
QPushButton* btn = (QPushButton*)ttb["customEditButton"];
btn->setText("Edit");
static bool kek = true;
tt::Page* editPage = (tt::Page*)ttb["Edit"];
QObject::connect(btn, &QPushButton::clicked, [editPage]()
{
if(kek)
editPage->hide();
else
editPage->show();
kek = !kek;
});
QObject::connect(tabToolbar, &tt::TabToolbar::SpecialTabClicked, this, [this]()
{
QMessageBox::information(this, "Kek", "Cheburek");
});
//create buttons for each style
tt::Group* stylesGroup = (tt::Group*)ttb["Styles"];
stylesGroup->AddSeparator();
QStringList styles = tt::GetRegisteredStyles();
for(int i=0; i<styles.size(); i++)
{
const QString styleName = styles.at(i);
QPushButton* btn = new QPushButton(styleName, this);
QObject::connect(btn, &QPushButton::clicked, [styleName, tabToolbar]() { tabToolbar->SetStyle(styleName); });
stylesGroup->AddWidget(btn);
}
tt::RegisterStyle("NoStyle", []()
{
tt::StyleParams* params = new tt::StyleParams();
params->UseTemplateSheet = false;
params->AdditionalStyleSheet = "";
return params;
});
btn = (QPushButton*)ttb["nativeStyleButton"];
btn->setText("No Style");
QObject::connect(btn, &QPushButton::clicked, [tabToolbar]() { tabToolbar->SetStyle("NoStyle"); });
btn = (QPushButton*)ttb["defaultStyleButton"];
btn->setText("Default");
QObject::connect(btn, &QPushButton::clicked, [tabToolbar]() { tabToolbar->SetStyle(tt::GetDefaultStyle()); });
再开一下json文件的内容
分别指定组的高度,每组容纳的最多行数,是否启用特殊标签,然后就是角落的action,然后是定义菜单栏的情况,最后是定义tab标签。
{
"groupHeight": 75,
"groupRowCount": 3,
"specialTab": true,
"cornerActions": [
...
],
"menus": [
...
],
"tabs": [
...
]
使用方式二:使用代码控制
首先看一下代码,
using namespace tt;
TabToolbar* tt = new TabToolbar(this, 75, 3);
addToolBar(Qt::TopToolBarArea, tt);
QMenu* menu = new QMenu(this);
menu->setObjectName("dummyMenu");
menu->addActions({ui->actionDummy});
tt->AddPage("File");
static bool kek = true;
Page* editPage = tt->AddPage("Edit");
Page* viewPage = tt->AddPage("View");
Group* g1 = viewPage->AddGroup("Group 1");
Group* g2 = viewPage->AddGroup("Group 2");
Group* g3 = viewPage->AddGroup("Group 3");
g1->AddAction(QToolButton::DelayedPopup, ui->actionOpen);
g1->AddSeparator();
g1->AddAction(QToolButton::DelayedPopup, ui->actionSave);
g1->AddAction(QToolButton::DelayedPopup, ui->actionSaveAs);
g2->AddAction(QToolButton::InstantPopup, ui->actionPolypaint, menu);
g2->AddAction(QToolButton::InstantPopup, ui->actionScale, menu);
g2->AddSeparator();
QTextEdit* te = new QTextEdit();
g2->AddWidget(te);
te->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
te->setMaximumWidth(100);
SubGroup* g2s = g2->AddSubGroup(SubGroup::Align::Yes);
g2s->AddAction(QToolButton::DelayedPopup, ui->actionUndo);
g2s->AddAction(QToolButton::DelayedPopup, ui->actionRedo);
g2s->AddAction(QToolButton::InstantPopup, ui->actionClose, menu);
g3->AddAction(QToolButton::MenuButtonPopup, ui->actionSettings, menu);
SubGroup* g3s = g3->AddSubGroup(SubGroup::Align::Yes);
g3s->AddHorizontalButtons({{QToolButton::DelayedPopup, ui->actionSave},
{QToolButton::InstantPopup, ui->actionPolypaint, menu},
{QToolButton::MenuButtonPopup, ui->actionSettings, menu}});
g3s->AddHorizontalButtons({{QToolButton::DelayedPopup, ui->actionUndo},
{QToolButton::DelayedPopup, ui->actionRedo},
{QToolButton::InstantPopup, ui->actionClose, menu}});
QCheckBox* ch = new QCheckBox("Check 1");
g3s->AddWidget(ch);
g3->AddSeparator();
SubGroup* g3ss = g3->AddSubGroup(SubGroup::Align::No);
QPushButton* btn = new QPushButton("Edit");
g3ss->AddWidget(btn);
g3ss->AddAction(QToolButton::DelayedPopup, ui->actionSaveAs);
QObject::connect(btn, &QPushButton::clicked, [editPage]()
{
if(kek)
editPage->hide();
else
editPage->show();
kek = !kek;
});
tt->AddPage("Help");
tt->SetSpecialTabEnabled(true);
tt->AddCornerAction(ui->actionHelp);
QObject::connect(tt, &TabToolbar::SpecialTabClicked, this, [this]()
{
QMessageBox::information(this, "Kek", "Cheburek");
});
然后我们来分析一下,这是怎么使用的
- 创建对象
using namespace tt; //使用库的名字空间
TabToolbar* tt = new TabToolbar(this, 75, 3); //初始化
addToolBar(Qt::TopToolBarArea, tt); //添加TabToolbar到tool工具栏
- 设计内容
//创建案例并绑定ui设计器里面的action
QMenu* menu = new QMenu(this);
menu->setObjectName("dummyMenu");
menu->addActions({ui->actionDummy});
//添加tab页
tt->AddPage("File");
static bool kek = true;
Page* editPage = tt->AddPage("Edit");//添加tab页,并获取对象
Page* viewPage = tt->AddPage("View");
Group* g1 = viewPage->AddGroup("Group 1"); //再tab页里面添加组
Group* g2 = viewPage->AddGroup("Group 2");
Group* g3 = viewPage->AddGroup("Group 3");
//各组控件的设置
g1->AddAction(QToolButton::DelayedPopup, ui->actionOpen);
g1->AddSeparator();
g1->AddAction(QToolButton::DelayedPopup, ui->actionSave);
g1->AddAction(QToolButton::DelayedPopup, ui->actionSaveAs);
g2->AddAction(QToolButton::InstantPopup, ui->actionPolypaint, menu);
g2->AddAction(QToolButton::InstantPopup, ui->actionScale, menu);
g2->AddSeparator();
QTextEdit* te = new QTextEdit();
g2->AddWidget(te);
te->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
te->setMaximumWidth(100);
SubGroup* g2s = g2->AddSubGroup(SubGroup::Align::Yes);
g2s->AddAction(QToolButton::DelayedPopup, ui->actionUndo);
g2s->AddAction(QToolButton::DelayedPopup, ui->actionRedo);
g2s->AddAction(QToolButton::InstantPopup, ui->actionClose, menu);
g3->AddAction(QToolButton::MenuButtonPopup, ui->actionSettings, menu);
SubGroup* g3s = g3->AddSubGroup(SubGroup::Align::Yes);
g3s->AddHorizontalButtons({{QToolButton::DelayedPopup, ui->actionSave},
{QToolButton::InstantPopup, ui->actionPolypaint, menu},
{QToolButton::MenuButtonPopup, ui->actionSettings, menu}});
g3s->AddHorizontalButtons({{QToolButton::DelayedPopup, ui->actionUndo},
{QToolButton::DelayedPopup, ui->actionRedo},
{QToolButton::InstantPopup, ui->actionClose, menu}});
QCheckBox* ch = new QCheckBox("Check 1");
g3s->AddWidget(ch);
g3->AddSeparator();
SubGroup* g3ss = g3->AddSubGroup(SubGroup::Align::No);
QPushButton* btn = new QPushButton("Edit");
g3ss->AddWidget(btn);
g3ss->AddAction(QToolButton::DelayedPopup, ui->actionSaveAs);
QObject::connect(btn, &QPushButton::clicked, [editPage]()
{
if(kek)
editPage->hide();
else
editPage->show();
kek = !kek;
});
tt->AddPage("Help");
tt->SetSpecialTabEnabled(true);
tt->AddCornerAction(ui->actionHelp); //绑定action
QObject::connect(tt, &TabToolbar::SpecialTabClicked, this, [this]()//绑定action
{
QMessageBox::information(this, "Kek", "Cheburek");
});
总结
TabToolbar
* tt = newTabToolbar
(); // 构造tabtoolbaraddToolBar
(Qt::TopToolBarArea, tt); // 添加对象到mainwindowsPage
* editPage = tt->AddPage
(“Edit”);//添加tab页,并获取对象Group
* g1 = editPage ->AddGroup
(“Group 1”); //tab页里面添加组- g1->
AddAction
(QToolButton::DelayedPopup, ui->actionOpen); // 添加action - g1->
AddSeparator
();// 添加分割器 - 不想写了,估计你也会了