草庐IT

Qt的开源库TabToolbar

TomKing-tm 2024-04-19 原文

开源地址: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);
  1. 创建自定义组件。将自定义组件和json中组件名绑定。就是如果想使用一个QTextEdit,那么在json文件中直接使用"itemType": "textEdit"字段就行。
    ttb.SetCustomWidgetCreator("textEdit", []() { return new QTextEdit(); });
    ttb.SetCustomWidgetCreator("checkBox", []() { return new QCheckBox(); });
    ttb.SetCustomWidgetCreator("pushButton", []() { return new QPushButton(); });
  1. 创建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");
    });

然后我们来分析一下,这是怎么使用的

  1. 创建对象
	using namespace tt;  //使用库的名字空间

    TabToolbar* tt = new TabToolbar(this, 75, 3); //初始化
    addToolBar(Qt::TopToolBarArea, tt); //添加TabToolbar到tool工具栏
  1. 设计内容
	//创建案例并绑定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 = new TabToolbar(); // 构造tabtoolbar
  • addToolBar(Qt::TopToolBarArea, tt); // 添加对象到mainwindows
  • Page* editPage = tt->AddPage(“Edit”);//添加tab页,并获取对象
  • Group* g1 = editPage ->AddGroup(“Group 1”); //tab页里面添加组
  • g1->AddAction(QToolButton::DelayedPopup, ui->actionOpen); // 添加action
  • g1->AddSeparator();// 添加分割器
  • 不想写了,估计你也会了

有关Qt的开源库TabToolbar的更多相关文章

  1. Qt Designer的简单使用 - 2

    在前面两节的例子中,主界面窗口的尺寸和标签控件显示的矩形区域等,都是用C++代码编写的。窗口和控件的尺寸都是预估的,控件如果多起来,那就不好估计每个控件合适的位置和大小了。用C++代码编写图形界面的问题就是不直观,因此Qt项目开发了专门的可视化图形界面编辑器——QtDesigner(Qt设计师)。通过QtDesigner就可以很方便地创建图形界面文件*.ui,然后将ui文件应用到源代码里面,做到“所见即所得”,大大方便了图形界面的设计。本节就演示一下QtDesigner的简单使用,学习拖拽控件和设置控件属性,并将ui文件应用到Qt程序代码里。使用QtDesigner设计界面在开始菜单中找到「Q

  2. 关于Qt程序打包后运行库依赖的常见问题分析及解决方法 - 2

    目录一.大致如下常见问题:(1)找不到程序所依赖的Qt库version`Qt_5'notfound(requiredby(2)CouldnotLoadtheQtplatformplugin"xcb"in""eventhoughitwasfound(3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentationfault,或者Illegalinstruction(coredumped)非法指令(4)ldd应用程序或者库,查看运行所依赖的库时,直接报段错误二.问题逐个分析,得出解决方法:(1)找不到程序所依赖的Qt库version`Qt_5'

  3. python - 开源 Twitter 克隆(在 Ruby/Python 中) - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭6年前。Improvethisquestion是否有任何用Ruby或Python编写的生产就绪的开源Twitter克隆?我对功能丰富的实现更感兴趣,而不仅仅是简单的Twitter消息(例如:API、FBconnect、通知等)谢谢!

  4. Gradle 自动化构建开源工具 - 2

    文章目录写在前面1、下载与安装(windows)1.1、idea中配置gradle2、基础知识(Gradle6.9为例)2.1、Gradle脚本语法2.1.1、dependsOn2.1.2、创建动态任务2.1.3、增加任务行为2.1.4、参数2.1.5、Ant任务2.1.6、方法2.1.7、默认任务2.1.6、依赖任务的不同输出3、java项目中使用3.1、在已有项目中构建gradle3.2、在新建项目时构建gradle(idea)3.3、gradle项目目录结构3.4、build.gradle3.4.1、plugins3.4.2、repositories3.4.3、dependencies3

  5. 停车系统源码-基于springboot+uniapp开源项目 - 2

    Iparking停车收费管理系统-可商用介绍Iparking是一款基于springBoot的停车收费管理系统,支持封闭车场和路边车场,支持微信支付宝多种支付渠道,支持多种硬件,涵盖了停车场管理系统的所有基础功能。技术栈Springboot,MybatisPlus,Beetl,Mysql,Redis,RabbitMQ,UniApp功能云端功能序号模块功能描述1系统管理菜单管理配置系统菜单2系统管理组织管理管理组织机构3系统管理角色管理配置系统角色,包含数据权限和功能权限配置4系统管理用户管理管理后台用户5系统管理租户管理多租户管理6系统管理公众号配置租户公众号配置7系统管理操作日志审计日志8系统

  6. ruby-on-rails - 有没有很好的引用(开源)Rails NoSQL应用程序? - 2

    我有兴趣了解使用nosql将如何影响rails应用程序的架构/设计/代码。有人知道使用nosql持久性的开源rails应用程序的一个好例子吗?谢谢 最佳答案 看看这些项目:卡桑德拉用法atDigg。卡桑德拉用法atTwitter。Friendly用法atFetLife(nsfw)。最后,MyNoSQL是一个提供nosql相关信息的好网站。 关于ruby-on-rails-有没有很好的引用(开源)RailsNoSQL应用程序?,我们在StackOverflow上找到一个类似的问题:

  7. Qt样式表之 QSS 语法介绍;QLineEdit、 - 2

     内容来自Qt样式表之QSS语法介绍-3YL的博客Qt样式表是一个可以自定义部件外观的十分强大的机制,可以用来美化部件。Qt样式表的概念、术语和语法都受到了HTML的层叠样式表(CascadingStyleSheets, CSS教程)的启发,不过与CSS不同的是,Qt样式表应用于部件的世界。类型选择器QPushButton匹配QPushButton及其子类的实例ID选择器QPushButton#okButton匹配所有objectName为okButton的QPushButton实例。 CSS常用样式1CSS文字属性注:px:相对长度单位,像素(Pixel)。pt:绝对长度单位,点(Point

  8. QT 设计一个串口调试工具,用一个工程就能轻松解决,外加虚拟串口工具模拟调试,在日常工作中可类比模块间通信,非常详细建议收藏 - 2

    QT串口调试工具第一节虚拟串口工具安装第二节QT创建一个基于QWidget的项目第三节UI界面设计第三节项目头文件widget.h第四节项目实现文件widget.cpp第五节main函数第六节编译结果重点第七节使用QT打包程序,不安装QT的电脑可使用第一节虚拟串口工具安装-----------------------------------------下载所需工具---------------------------------------------------------------------链接:https://pan.baidu.com/s/1QkT36S4EnH2HEAhZ1TZ8

  9. ruby-on-rails - 请向我推荐一些需要编写文档/测试的 rails/ruby 开源代码 - 2

    关闭。这个问题不符合StackOverflowguidelines。它目前不接受答案。要求我们推荐或查找书籍、工具、软件库、教程或其他场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,请描述问题以及迄今为止为解决该问题所做的工作。关闭8年前。Improvethisquestion在过去的4个月左右的时间里,我一直在使用ruby​​onrails,我真的很喜欢开源的整个概念。我知道它不是ruby​​/rails独有的,但来自Windows编程,这是我第一次真正接触它。我想尽我所能“回馈”,但我觉得我无法贡献任何有值(value

  10. ruby-on-rails - 我如何找到可以贡献的开源项目(Ruby、Rails) - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭7年前。Improvethisquestion我是一名RubyonRails开发人员,手头有一些时间。我想利用这段时间通过为开源项目做贡献来回馈和学习。我不是一流的程序员,想从小做起。在哪里可以找到Ruby或Rails中的小型开源项目?我该如何贡献?亚历克斯

随机推荐