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

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QToolBar>

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

mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>
#include <QMessageBox>


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);
}

ui

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

main.cpp

cpp 复制代码
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

分析

以上示例,主要函数为:

cpp 复制代码
private:
    void setAction(QToolBar* pTB, QAction* pActSender, bool checked);
cpp 复制代码
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;
            }
        }
    }
}

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

此外:

cpp 复制代码
ui->statusBar->showMessage(QString("我是 %1").arg(pActClone->text()), 2000);

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

结论

学以致用。

相关推荐
木头软件1 分钟前
批量将 Word 文档重命名为其标题
开发语言·c#·word
fantasy5_51 分钟前
C++ 智能指针深度解析:原理、实现与实战避坑
java·开发语言·c++
ERROR:992 分钟前
野路子:把海量文档一次性转换成多个PPT
开发语言·人工智能·c#
凌冰_2 分钟前
JAVA与MySQL实现银行管理系统
java·开发语言·mysql
CodeCraft Studio3 分钟前
国产化Excel开发组件Spire.XLS教程:以Python编程方式在Excel中高亮重复值
开发语言·python·excel·spire.xls·excel自动化·excel高亮重复值·python处理excel
NineData4 分钟前
NineData 数据库 DevOps 正式支持谷歌云,全面接入 GCP 数据源
运维·数据库·devops·ninedata·gcp·玖章算术·数据智能管理平台
韩立学长9 分钟前
Springboot考研自习室预约管理系统1wdeuxh6(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
木千10 分钟前
Qt中关于QTableWidget成员函数selectedItems和itemAt(QPoint)无法获取无数据Item的处理方式
开发语言·qt
小鸡吃米…12 分钟前
Python - 命令行参数
开发语言·python
2503_9284115613 分钟前
12.18 中后台项目-权限管理
前端·javascript·数据库