• Qt之菜单栏、工具栏、状态栏介绍及工具栏QAction的动态增删显示实现方式


    目的

    端应用程序或者编辑器基本都支持工具栏快捷功能的动态增删,即通过在菜单栏上打钩就可以在工具栏上看到相应功能的快捷按钮,取消打钩则在工具栏上就移除了该功能的快捷按钮。那么Qt如何实现这个功能,本篇目的就是记录实现此功能的方法及思路。

    效果

    先看下动态效果:

    菜单栏动态添加动作到工具栏

    介绍

    首先,说下菜单栏,工具栏和状态栏区别:

    • 菜单栏:一般在窗体标题的下方,有下拉选项,和可有多级子菜单。
    • 工具栏:一般在菜单栏下方,可上下左右四个方向调整位置,默认在菜单栏下方(即上方向),方便操作,直接点击即可触发想要的工作。
    • 状态栏:一般在窗体最下方,用于永久或者暂时显示某些状态信息等。

    UI如下图所示:
    在这里插入图片描述

    Qt之QMenuBar(菜单栏)、QToolBar(工具栏)、QStatusBar(状态栏)操作说明

    可在帮助里,选择索引,输入想查找的类,比如qmenubar,一般选择第一个结果(可根据需要选择其他),会弹出选择主题,选择库版本,会跳到对应的类介绍页
    在这里插入图片描述
    点击More...,会跳到Detailed Description,查看此类详细介绍,或者点击Public Functions查看此类公有成员方法。

    QMenuBar(菜单栏)

    在这里插入图片描述

    QStatusBar(状态栏)

    在这里插入图片描述

    QToolBar(工具栏)

    在这里插入图片描述
    在这里插入图片描述

    菜单栏对工具栏进行动作动态配置的实现思路

    1. 首先,菜单栏的子菜单和动作是已知并存在的
    2. 动作设置为可选择的
    3. 当点击动作时,触发triggered(bool checked)信号
    4. 绑定槽,然后根据checked状态,进行工具栏动态创建动作或者移除动作
    5. 当点击工具栏动作时,触发动作实际功能

    示例

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include 
    #include 
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private:
        void setAction(QToolBar* pTB, QAction* pActSender, bool checked);
    
    private slots:
        void on_actionact11_triggered(bool checked);
    
        void on_actionact12_triggered(bool checked);
    
        void on_actionact21_triggered(bool checked);
    
        void on_actionact22_triggered(bool checked);
    
        void on_actionact31_triggered(bool checked);
    
        void on_actionact32_triggered(bool checked);
    
        void on_actionact33_triggered(bool checked);
    
    private:
        Ui::MainWindow *ui;
    
        QToolBar*       m_pTB1;
        QToolBar*       m_pTB2;
        QToolBar*       m_pTB3;
    };
    
    #endif // MAINWINDOW_H
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include 
    #include 
    
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        m_pTB1 = new QToolBar("tb1");
        m_pTB2 = new QToolBar("tb2");
        m_pTB3 = new QToolBar("tb3");
    
        addToolBar(m_pTB1);
        addToolBar(m_pTB2);
        addToolBar(m_pTB3);
    
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::setAction(QToolBar *pTB, QAction *pActSender, bool checked)
    {
        if(checked){
            foreach (QAction* pAct, pTB->actions()) {
                if(pAct->text().compare(pActSender->text()) == 0)
                {
                    return;
                }
            }
    
            QAction* pActClone = new QAction(pActSender->text(), this);
            connect(pActClone, &QAction::triggered, this, [this, pActClone](){
                ui->statusBar->showMessage(QString("我是 %1").arg(pActClone->text()), 2000);
                QMessageBox::information(this, "提示", QString("我是 %1").arg(pActClone->text()));
            });
            pTB->insertAction(0, pActClone);
        }
        else {
            foreach (QAction* pAct, pTB->actions()) {
                if(pAct->text().compare(pActSender->text()) == 0)
                {
                    pTB->removeAction(pAct);
                    return;
                }
            }
        }
    }
    
    void MainWindow::on_actionact11_triggered(bool checked)
    {
        QAction* pActSender = dynamic_cast<QAction*>(sender());
        setAction(m_pTB1, pActSender, checked);
    }
    
    void MainWindow::on_actionact12_triggered(bool checked)
    {
        QAction* pActSender = dynamic_cast<QAction*>(sender());
        setAction(m_pTB1, pActSender, checked);
    }
    
    void MainWindow::on_actionact21_triggered(bool checked)
    {
        QAction* pActSender = dynamic_cast<QAction*>(sender());
        setAction(m_pTB2, pActSender, checked);
    }
    
    void MainWindow::on_actionact22_triggered(bool checked)
    {
        QAction* pActSender = dynamic_cast<QAction*>(sender());
        setAction(m_pTB2, pActSender, checked);
    }
    
    void MainWindow::on_actionact31_triggered(bool checked)
    {
        QAction* pActSender = dynamic_cast<QAction*>(sender());
        setAction(m_pTB3, pActSender, checked);
    }
    
    void MainWindow::on_actionact32_triggered(bool checked)
    {
        QAction* pActSender = dynamic_cast<QAction*>(sender());
        setAction(m_pTB3, pActSender, checked);
    }
    
    void MainWindow::on_actionact33_triggered(bool checked)
    {
        QAction* pActSender = dynamic_cast<QAction*>(sender());
        setAction(m_pTB3, pActSender, checked);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    ui

    	// ui的话,主要是添加一些菜单和动作,工具栏是代码实现的
    	// 动作名称
    
    • 1
    • 2

    在这里插入图片描述

    main.cpp

    #include "mainwindow.h"
    #include 
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    分析

    以上示例,主要函数为:

    private:
        void setAction(QToolBar* pTB, QAction* pActSender, bool checked);
    
    • 1
    • 2
    void MainWindow::setAction(QToolBar *pTB, QAction *pActSender, bool checked)
    {
        if(checked){
            foreach (QAction* pAct, pTB->actions()) {
                if(pAct->text().compare(pActSender->text()) == 0)
                {
                    return;
                }
            }
    
            QAction* pActClone = new QAction(pActSender->text(), this);
            connect(pActClone, &QAction::triggered, this, [this, pActClone](){
                ui->statusBar->showMessage(QString("我是 %1").arg(pActClone->text()), 2000);
                QMessageBox::information(this, "提示", QString("我是 %1").arg(pActClone->text()));
            });
            pTB->insertAction(0, pActClone);
        }
        else {
            foreach (QAction* pAct, pTB->actions()) {
                if(pAct->text().compare(pActSender->text()) == 0)
                {
                    pTB->removeAction(pAct);
                    return;
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    根据传入的参数,进行工具栏动态的创建。
    此外:

    ui->statusBar->showMessage(QString("我是 %1").arg(pActClone->text()), 2000);
    
    • 1

    上述代码是 暂时显示文本,时间是2000ms,之后会消失。

    结论

    学以致用。

  • 相关阅读:
    Android Java反射与Proxy动态代理详解与使用基础篇(一)
    第 4 章 ROS 运行管理 1 —— 元功能包 plumbing_my / 节点管理launch文件 launch01_basic
    ASP.NET Core 6框架揭秘实例演示[11]:诊断跟踪的几种基本编程方式
    网课答案查询单页面附接口
    MVCC - Read View的可见性判断理解
    vuex环境配置及使用
    shell字符串处理之字符串替换、截断
    基础 | 并发编程 - [CAS & 原子类]
    SwiftUI 为不同视图限制不同的屏幕旋转方向
    一个域名可以对应多个IP吗?如何通过DNS实现?
  • 原文地址:https://blog.csdn.net/MrHHHHHH/article/details/134046036