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

news2025/1/12 16:17:50

目的

端应用程序或者编辑器基本都支持工具栏快捷功能的动态增删,即通过在菜单栏上打钩就可以在工具栏上看到相应功能的快捷按钮,取消打钩则在工具栏上就移除了该功能的快捷按钮。那么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 <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

#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

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

在这里插入图片描述

main.cpp

#include "mainwindow.h"
#include <QApplication>

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

    return a.exec();
}

分析

以上示例,主要函数为:

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

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

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

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

结论

学以致用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1137376.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

cmd 命令关闭占用端口

工作中还是偶尔会遇到端口号被占用的情况&#xff0c;之前也有写过另一种关闭方式&#xff0c;但是发现没有命令方便&#xff0c;所以记录一下。 1、 查看 8081 端口占用的 pid 。 命令&#xff1a;netstat -ano |findstr 8081 由上图可知&#xff0c;占用 8081 端口的进程 id…

折叠式菜单怎么做编程,初学编程系统化教程初级1上线

中文编程系统化教程&#xff0c;不需英语基础&#xff0c;学习链接——入门篇课程 https://edu.csdn.net/course/detail/39036中文编程系统化教程&#xff0c;不需英语基础&#xff0c;学习链接—— 初级1课程 https://edu.csdn.net/course/detail/39061 ——————————…

C语言输出以下图案

图案&#xff1a; * * * * * * * * * * * * * * * * * * * * * * * * * 完整代码&#xff1a; /* 输出以下图案 * * * * * * * * * * * * * * * * * * * * * * * * * */ #include<stdio.h>int main(){//图案的行数int n5;for (int i 0; i < n; i){//每一行开头空格…

通过profibus PA转Modbus rtu协议网关把RTU数据传到pa设备上

远创智控PA转modbus rtu协议网关YC-PA-485&#xff0c;解决您的协议转换难题。 这款PA转Modbus RTU协议网关&#xff0c;将Profibus PA和Modbus RTU专用通讯协议进行桥接&#xff0c;为您的数据传输提供稳定、高效的解决方案。它符合Modbus通讯协议&#xff0c;允许Modbus设备…

基于Java的学生在线课程学习系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

架构设计基础

一、架构图 二、系统背景 业务发展迅速&#xff0c;积累了大量的数据资产&#xff0c;大数据团队承担数据串联、沉淀&#xff0c;反哺和赋能业务的重要职责。大数据团队协同各部门打造了玩个大狗魔方、大狗宝盒数据产品&#xff0c;提供data-center应用发力数据中台&#xff0…

leetcode做题笔记203. 移除链表元素

给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5]示例 2&#xff1a; 输入&#xff1a…

redis archive github

https://github.com/redis/redis/releases/tag/7.2.2https://github.com/redis/redis/releases/tag/7.2.2

JS38 高频数据类型

题目来源&#xff1a; 高频数据类型_牛客题霸_牛客网 (nowcoder.com) JS38 高频数据类型 描述 请补全JavaScript代码&#xff0c;要求找到参数数组中出现频次最高的数据类型&#xff0c;并且计算出出现的次数&#xff0c;要求以数组的形式返回。 注意&#xff1a; 1. 基本数据…

【VASP】QVASP 的使用

【VASP】QVASP 的使用 QVASP 的介绍Qvasp 安装使用、测试和算例ELF电荷局域函数计算输入文件简述 QVASP 的介绍 下载地址&#xff1a;https://sourceforge.net/projects/qvasp/ qvasp定位于开发包含VASP输入文件前处理、输出文件后处理的基本功能&#xff0c;同时&#xff0c…

threejs(6)-操控物体实现家居编辑器

// 导入threejs import * as THREE from "three"; // 导入轨道控制器 import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; // 导入lil.gui import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";…

使用ControlNet生成视频(Pose2Pose)

目录 ControlNet 介绍 ControlNet 14种模型分别是用来做什么的 ControlNet 运行环境搭建 用到的相关模型地址 ControlNet 介绍 ControlNet 是一种用于控制扩散模型的神经网络结构&#xff0c;可以通过添加额外的条件来实现对图像生成的控制。它通过将神经网络块的权重复制到…

排序-基数排序

排序思路&#xff1a;抽象实现多个桶用来储存所需要排序的基数&#xff0c;再递归的调用到每一次数上&#xff08;通俗点讲&#xff0c;先按个位进行分类&#xff0c;再按十位进行分类&#xff0c;依次排到最高位&#xff0c;最后将所有分类的数连在一起就是排完的序列&#xf…

Pytorch代码入门学习之分类任务(三):定义损失函数与优化器

一、定义损失函数 1.1 代码 criterion nn.CrossEntropyLoss() 1.2 损失函数简介 神经网络的学习通过某个指标表示目前的状态&#xff0c;然后以这个指标为基准&#xff0c;寻找最优的权重参数。神经网络以某个指标为线索寻找最优权重参数&#xff0c;该指标称为损失函数&am…

M1安装python3.12

1.下载pkg文件 Python Releases for macOS | Python.org 2.安装 下一步下一步即可 3.配置环境变量 不配置也可以&#xff0c;直接python3.12即可进入python环境。 4.python3.12改为python 每次少敲4次键盘也挺爽的。效果&#xff1a; 实现步骤&#xff1a; python3.12的默…

DeepinV20实现使用CapsLock键切换输入法

概览 起因参考资料解决问题1. 删除CapsLock键映射关系2. 新建CapsLock键映射关系3. 建立配置文件4. **注销用户或者重启电脑**5. 修改切换输入法快捷键6. 测试输入 起因 看同事的MacBook可以使用CapsLock键切换输入法&#xff0c;而我作为Shift党CapsLock键几乎不使用&#xf…

HackTheBox-Starting Point--Tier 1---Appointment

文章目录 一 题目二 实验过程 一 题目 Tags Web、Databases、Injection、Apache、MariaDB、PHP、SQL、Reconnaissance、SQL Injection译文&#xff1a;Web、数据库、注入、Apache、MariaDB、PHP、SQL、侦察、SQL 注入Connect To attack the target machine, you must be on …

Spring Boot拓展XML格式的请求和响应

在我们开发过程中&#xff0c;我们经常使用的参数绝大多少事HTML和JSON格式的请求和响应处理&#xff0c;但是我们在实际开发过程中&#xff0c;我们可能经历一些&#xff0c;比如对于XML格式的请求&#xff0c;我们在后端应该如何接收&#xff0c;并且如何将XML格式的参数变成…

电源控制系统架构(PCSA)电源控制挑战

安全之安全(security)博客目录导读 下图显示了一个简化的SoC示例&#xff0c;这个例子是从high-level的功能层面来说明的。 该示例以移动设备为中心&#xff0c;但可用于演示在任何SoC配置中高层次的电源管理挑战。 除了示例所示的主要功能(包括处理器、通信功能和公共系统功能…

P1966 [NOIP2013 提高组] 火柴排队

洛谷的一道原题&#xff0c;方法有很多&#xff0c;树状数组以及排序&#xff0c;对刚学树状数组的人来说用排序会比较好理解。 本题最重要的结论就是&#xff0c;要保证两个数组中相同位置的差最小&#xff0c;但是不一定两个数组中数值相同&#xff0c;所以只需要保证相同位…