在Qt窗口中添加右键菜单

news2024/11/15 5:07:58

在Qt窗口中添加右键菜单

  • 基于鼠标的事件实现
    • 流程
    • demo
  • 基于窗口的菜单策略实现
    • Qt::DefaultContextMenu
    • Qt::ActionsContextMenu
    • Qt::CustomContextMenu
      • 信号API

基于鼠标的事件实现

流程

需要使用:事件处理器函数(回调函数)

  1. 在当前窗口类中重写鼠标操作相关的的事件处理器函数,有两个可以选择
// 以下两个事件二选一即可, 只是事件函数被调用的时机不同罢了
// 这个时机对右键菜单的显示没有任何影响
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event);
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event);
  1. 在数据表事件处理器函数内部判断是否按下了鼠标右键
  2. 如果按下了鼠标右键创建菜单对象(也可以提前先创建处理), 并将其显示出来
// 关于QMenu类型的菜单显示需要调用的 API
// 参数 p 就是右键菜单需要显示的位置, 这个坐标需要使用屏幕坐标
// 该位置坐标一般通过调用 QCursor::pos() 直接就可以得到了
QAction *QMenu::exec(const QPoint &p, QAction *action = nullptr);

demo

在头文件中,添加 mousePressEvent 函数的声明

在这里插入图片描述

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;


protected:
    // 鼠标按下, 该函数被Qt框架调用, 需要重写该函数
    void mousePressEvent(QMouseEvent *event);
};
#endif // MAINWINDOW_H

在对应的cpp中,添加 mousePressEvent 函数的定义

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QIcon"
#include "QTextEdit"
#include "QMessageBox"
#include "QMouseEvent"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 创建图标对象
    QIcon Q(":/new/prefix1/img/a.png");
    // QWidget类的 公共成员函数
    this->setWindowIcon(Q);

    // 给窗口设置图标
    // 弊端: 发布的 exe 必须要加载 d:\\pic\\1.ico 如果当前主机对应的目录中没有图片, 图标就无法被加载
    // 发布 exe 需要额外发布图片, 将其部署到某个目录中
    //setWindowIcon(QIcon("d:\\pic\\1.ico"));



    //使用API布局
    // 创建符窗口对象
    //QWidget *window1 = new QWidget();

    // 创建若干个子窗口对象
    QPushButton *button1 = new QPushButton("One");
    QPushButton *button2 = new QPushButton("Two");
    QPushButton *button3 = new QPushButton("Three");
    QPushButton *button4 = new QPushButton("Four");
    QPushButton *button5 = new QPushButton("Five");

    // 创建水平布局对象
    QHBoxLayout *layout1 = new QHBoxLayout;
    // 将子窗口添加到布局中
    layout1->addWidget(button1);
    layout1->addWidget(button2);
    layout1->addWidget(button3);
    layout1->addWidget(button4);
    layout1->addWidget(button5);

    // 将水平布局设置给父窗口对象
    this->ui->widget_3->setLayout(layout1);
    // 显示父窗口
    this->ui->widget_3->show();


    //使用API布局
    //创建垂直布局
    // 创建符窗口对象
    //QWidget *window2 = new QWidget;
    // 创建若干个子窗口对象
    QPushButton *button21 = new QPushButton("One");
    QPushButton *button22 = new QPushButton("Two");
    QPushButton *button23 = new QPushButton("Three");
    QPushButton *button24 = new QPushButton("Four");
    QPushButton *button25 = new QPushButton("Five");

    // 创建垂直布局对象
    QVBoxLayout *layout2 = new QVBoxLayout;
    // 将子窗口添加到布局中
    layout2->addWidget(button21);
    layout2->addWidget(button22);
    layout2->addWidget(button23);
    layout2->addWidget(button24);
    layout2->addWidget(button25);

    // 将水平布局设置给父窗口对象
    this->ui->widget_4->setLayout(layout2);
    // 显示父窗口
    this->ui->widget_4->show();


    //使用API布局
    //创建网格布局
    // 创建父窗口对象
    //QWidget* window3 = new QWidget;
    // 创建子窗口对象
    QPushButton *button31 = new QPushButton("One");
    QPushButton *button32 = new QPushButton("Two");
    QPushButton *button33 = new QPushButton("Three");
    QPushButton *button34 = new QPushButton("Four");
    QPushButton *button35 = new QPushButton("Five");
    QPushButton *button6 = new QPushButton("Six");
    // 多行文本编辑框
    QTextEdit* txedit3 = new QTextEdit;
    txedit3->setText("我占用了两行两列的空间哦。");

    QGridLayout* layout = new QGridLayout;
    // 按钮起始位置: 第1行, 第1列, 该按钮占用空间情况为1行1列
    layout->addWidget(button1, 0, 0);
    // 按钮起始位置: 第1行, 第2列, 该按钮占用空间情况为1行1列
    layout->addWidget(button2, 0, 1);
    // 按钮起始位置: 第1行, 第3列, 该按钮占用空间情况为1行1列
    layout->addWidget(button3, 0, 2);
    // 编辑框起始位置: 第2行, 第1列, 该按钮占用空间情况为2行2列
    layout->addWidget(txedit3, 1, 0, 2, 2);
    // 按钮起始位置: 第2行, 第3列, 该按钮占用空间情况为1行1列
    layout->addWidget(button4, 1, 2);
    // 按钮起始位置: 第3行, 第3列, 该按钮占用空间情况为1行1列
    layout->addWidget(button5, 2, 2);
    // 按钮起始位置: 第4行, 第1列, 该按钮占用空间情况为1行3列
    layout->addWidget(button6, 3, 0, 1, 3);

    // 网格布局设置给父窗口对象
    this->ui->widget_5->setLayout(layout);
    // 显示父窗口
    this->ui->widget_5->show();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::mousePressEvent(QMouseEvent *event){
    // 判断用户按下的是哪一个鼠标键
    if(event->button() == Qt::RightButton)
    {
        // 弹出一个菜单, 菜单项是 QAction 类型
        QMenu menu;
        QAction* act = menu.addAction("C++");
        connect(act, &QAction::triggered, this, [=]()
        {
            QMessageBox::information(this, "title", "您选择的是C++...");
        });
        menu.addAction("Java");
        menu.addAction("Python");
        menu.exec(QCursor::pos()); // 右键菜单被模态显示出来了
    }

}

效果

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

我稍作修改,添加左击和右击的效果:

void MainWindow::mousePressEvent(QMouseEvent *event){
    // 判断用户按下的是哪一个鼠标键
    if(event->button() == Qt::RightButton)
    {
        // 弹出一个菜单, 菜单项是 QAction 类型
        QMenu menu;
        QAction* act1 = menu.addAction("C++");
        connect(act1, &QAction::triggered, this, [=]()
        {
            QMessageBox::information(this, "title", "您选择的是C++...");
        });
        QAction* act2 =menu.addAction("Java");
        connect(act2, &QAction::triggered, this, [=]()
        {
            QMessageBox::information(this, "title", "您选择的是JAVA...");
        });
        QAction* act3 =menu.addAction("Python");
        connect(act3, &QAction::triggered, this, [=]()
        {
            QMessageBox::information(this, "title", "您选择的是PYthon...");
        });
        menu.exec(QCursor::pos()); // 右键菜单被模态显示出来了
    }
    if(event->button() == Qt::LeftButton)
    {
        // 弹出一个菜单, 菜单项是 QAction 类型
        QMenu menu;
        QAction* act = menu.addAction("hello");
        connect(act, &QAction::triggered, this, [=]()
        {
            QMessageBox::information(this, "title", "您使用鼠标左键点击了一下");
        });
        menu.exec(QCursor::pos()); // 右键菜单被模态显示出来了

    }

}

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

在这里插入图片描述

基于窗口的菜单策略实现

这种方式是使用 Qt 中 QWidget类中的右键菜单函数 QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy) 来实现

API如下:

// 函数原型:
void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy);
参数: 	
  - Qt::NoContextMenu	     --> 不能实现右键菜单
  - Qt::PreventContextMenu   --> 不能实现右键菜单
  - Qt::DefaultContextMenu   --> 基于事件处理器函数 QWidget::contextMenuEvent() 实现
  - Qt::ActionsContextMenu   --> 添加到当前窗口中所有 QAction 都会作为右键菜单项显示出来
  - Qt::CustomContextMenu    --> 基于 QWidget::customContextMenuRequested() 信号实现

Qt::DefaultContextMenu

第一步:在相应的窗口的类的头文件中添加这个函数 QWidget::contextMenuEvent() 的声明
在这里插入图片描述

第二步在这个窗口类的构造函数设置右键菜单策略

在这里插入图片描述

第三步在这个窗口类的源文件中重写事件处理器函数 contextMenuEvent()
在这里插入图片描述

Qt::ActionsContextMenu

使用这个策略实现右键菜单, 是最简单的一种, 我们只需要创建一些 QAction类型的对象并且将他们添加到当前的窗口中, 当我们在窗口中点击鼠标右键这些QAction类型的菜单项就可以显示出来了。

Qmainwindow的调用代码:
在这里插入图片描述
在mydialog2中:
在这里插入图片描述

#include "mydialog2.h"
#include "ui_mydialog2.h"
#include "QAction"
#include "QMessageBox"

myDialog2::myDialog2(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::myDialog2)
{
    ui->setupUi(this);

    // 只要将某个QAction添加给对应的窗口, 这个action就是这个窗口右键菜单中的一个菜单项了
    // 在窗口中点击鼠标右键, 就可以显示这个菜单
    setContextMenuPolicy(Qt::ActionsContextMenu);
    // 给当前窗口添加QAction对象
    QAction* act1  = new QAction("C++");
    QAction* act2 = new QAction("Java");
    QAction* act3  = new QAction("Python");
    this->addAction(act1);
    this->addAction(act2);
    this->addAction(act3);
    connect(act1, &QAction::triggered, this, [=]()
    {
         QMessageBox::information(this, "title", "您选择的是C++...");
    });



}

myDialog2::~myDialog2()
{
    delete ui;
}

Qt::CustomContextMenu

使用这个策略实现右键菜单, 当点击鼠标右键,窗口会产生一个 QWidget::customContextMenuRequested() 信号,注意仅仅只是发射信号,意味着要自己写显示右键菜单的槽函数(slot),这个信号是QWidget唯一与右键菜单有关的信号。

信号API

// 注意: 信号中的参数pos为当前窗口的坐标,并非屏幕坐标,右键菜单显示需要使用屏幕坐标
[signal] void QWidget::customContextMenuRequested(const QPoint &pos)

在这里插入图片描述

#include "mydialog3.h"
#include "ui_mydialog3.h"
#include "QMenu"
#include "QMessageBox"

myDialog3::myDialog3(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::myDialog3)
{
    ui->setupUi(this);

    // 策略 Qt::CustomContextMenu
    // 当在窗口中点击鼠标右键, 窗口会发出一个信号: QWidget::customContextMenuRequested()
    // 对应发射出的这个信号, 需要添加一个槽函数, 用来显示右键菜单
    this->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(this, &QDialog::customContextMenuRequested, this, [=](const QPoint &pos)
    {
        // 参数 pos 是鼠标按下的位置, 但是不能直接使用, 这个坐标不是屏幕坐标, 是当前窗口的坐标
        // 如果要使用这个坐标需要将其转换为屏幕坐标
        QMenu menu;
        QAction* act = menu.addAction("C++");
        connect(act, &QAction::triggered, this, [=]()
        {
            QMessageBox::information(this, "title", "您选择的是C++...");
        });
        QAction* act2 = menu.addAction("Java");
        connect(act2, &QAction::triggered, this, [=]()
        {
            QMessageBox::information(this, "title", "您选择的是加瓦");
        });
        menu.addAction("Python");
        // menu.exec(QCursor::pos());
        // 将窗口坐标转换为屏幕坐标
        QPoint newpt = this->mapToGlobal(pos);
        menu.exec(newpt);
    });

}

myDialog3::~myDialog3()
{
    delete ui;
}

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

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

相关文章

Python支持下最新Noah-MP陆面模式站点、区域模拟及可视化分析技术教程

详情点击公众号链接&#xff1a;Python支持下最新Noah-MP陆面模式站点、区域模拟及可视化分析技术教程 Noah-MP 5.0模型&模型所需环境的搭建 陆面过程的主要研究内容&#xff08;陆表能量平衡、水循环、碳循环等&#xff09;&#xff0c;陆面过程研究的重要性。 图 1 陆面…

MyBatis-Plus快速开始[MyBatis-Plus系列] - 第482篇

悟纤&#xff1a;师傅&#xff0c;MyBatis-Plus被你介绍的这么神乎其乎&#xff0c;咱们还是来的点实际的吧。 师傅&#xff1a;那真是必须的&#xff0c;学习技术常用的一种方法&#xff0c;就是实践。 悟纤&#xff1a;贱贱更健康。 师傅&#xff1a;这… 师傅&#xff1a;…

”源启,征程“新员工入职考试题及答案

中电金信&#xff0c;新员工入职必修课《源启&#xff0c;征程》考试题及答案。 源启&#xff0c;征程 单选题&#xff0c;每题仅有一个正确的选项.&#xff08;本题型共有5题&#xff09; 1.“源启”诞生的背景是什么&#xff1f;&#xff08;10分&#xff09; A、国际关系…

macbook 加载模型报错:failed to load model

环境&#xff1a;macbook m1 conda python3.9 加载模型链接为&#xff1a;ggml-model-q4_0.bin 加载方式&#xff1a; from langchain.embeddings import LlamaCppEmbeddings embeddings LlamaCppEmbeddings(model_pathllama_path) 在linux上加载是正常的&#xff0c;但是…

互联网医院|线上医疗提升就医效率

互联网医院是一款在线医疗服务平台&#xff0c;旨在解决患者就医难、看病贵的问题。通过该应用&#xff0c;用户可以在线咨询医生、挂号就医、获取医疗信息和健康管理等服务&#xff0c;随着这几年人们对于线上医疗的认可&#xff0c;互联网医院系统功能也越来越完善&#xff0…

(二)Linux中安装docker(一篇就够)

一、安装docker &#xff08;1&#xff09;卸载系统之前的 docker 复制以下下命令执行&#xff1a; sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine执行结果&…

使用vscode编写插件-php语言

https://blog.csdn.net/qq_45701130/article/details/125206645 一、环境搭建 1、安装 Visual Studio Code 2、安装 Node.js 3、安装 Git 4、安装生产插件代码的工具&#xff1a;npm install -g yo generator-code 二、创建工程 yo code 选择项解释&#xff1a; 选择编写扩…

Docker数据管理、网络通信和镜像创建

一、Docker 数据管理1、数据卷2、数据卷容器3、端口映射4、容器互联 二、Docker 镜像的创建1、基于现有的镜像创建1.1 首先启动一个镜像&#xff0c;在容器里做修改1.2 然后将修改后的容器提交为新的镜像&#xff0c;需要使用该容器的 ID 号创建新镜像 2、基于本地的模版创建3、…

RunnerGo中WebSocket、Dubbo、TCP/IP三种协议接口测试详解

大家好&#xff0c;RunnerGo作为一款一站式测试平台不断为用户提供更好的使用体验&#xff0c;最近得知RunnerGo新增对&#xff0c;WebSocket、Dubbo、TCP/IP&#xff0c;三种协议API的测试支持&#xff0c;本篇文章跟大家分享一下使用方法。 WebSocket协议 WebSocket 是一种…

【LeetCode】538.把二叉搜索树转换为累加树

题目 给出二叉 搜索 树的根节点&#xff0c;该树的节点值各不相同&#xff0c;请你将其转换为累加树&#xff08;Greater Sum Tree&#xff09;&#xff0c;使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提醒一下&#xff0c;二叉搜索树满足下列约束条件…

NAS个人云存储 - 手把手教你搭建Nextcloud个人云盘并实现公网远程访问

文章目录 摘要1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名 摘要 Nextcloud,它是ownCloud的一个分支,是一个文件共享服…

VSCode好用的插件

文章目录 前言1.Snippet Creator & easy snippet&#xff08;自定义代码&#xff09;2.Indent Rainbow&#xff08;代码缩进&#xff09;3.Chinese (Simplified) Language Pack&#xff08;中文包&#xff09;4.Path Intellisense&#xff08;路径提示&#xff09;5.Beauti…

GitKraken 详细图文教程

前言 写这篇文章的原因是组内的产品和美术同学&#xff0c;开始参与到git工作流中&#xff0c;但是网上又没有找到一个比较详细的使用教程&#xff0c;所以干脆就自己写了一个[doge]。文章的内容比较基础&#xff0c;介绍了Git内的一些基础概念和基本操作&#xff0c;适合零基…

游戏反外挂方案解析

近年来&#xff0c;游戏市场高速发展&#xff0c;随之而来的还有图谋利益的游戏黑产。在利益吸引下&#xff0c;游戏黑产扩张迅猛&#xff0c;已发展成具有庞大规模的产业链&#xff0c;市面上游戏受其侵扰的案例屡见不鲜。 据《FairGuard游戏安全2022年度报告》数据统计&…

明星翻包口播介绍产品视频的创意与实践

在当前社交媒体充斥着各种内容的时代&#xff0c;创意而有趣的内容形式成为品牌吸引受众目光的关键。明星翻包口播介绍产品视频&#xff0c;作为一种新颖的内容形式&#xff0c;不仅满足了观众对明星生活的好奇心&#xff0c;还将产品介绍融入其中&#xff0c;为品牌推广带来全…

Spring练习---28 (用户表和角色表分析,角色列表展示,角色层和Dao层的设置,页面展示操作)

84、下面进入我们的业务层面&#xff0c;进入我们的业务层面我们先分析一个东西&#xff0c;我们要分析用户和角色的关系&#xff0c;因为我们只有在分析完用户和角色之间的关系后&#xff0c;我们才知道表的关系&#xff0c;实体的关系 85、现在我们先画一张表&#xff0c;分析…

传统节日民俗文化及民间故事推广系统 微信小程序

傣族节日及民间故事推广小程序是在的数据存储主要通过MySQL。用户在使用应用时产生的数据通过java语言传递给数据库。通过此方式促进傣族节日及民间故事推广信息流动和数据传输效率&#xff0c;提供一个内容丰富、功能多样、易于操作的平台。述了数据库的设计&#xff0c;系统的…

Application of Acrel Earth Leakage Relay in Intell

安科瑞 华楠 Abstract: the necessity of applying residual current relay in intelligent building is analyzed, the main functions, working principle, classification situation of ASJ residual current relay are introduced, and the principles and precautions in…

Everything+cpolar搭建在线资料库,实现随时随地访问

Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问 文章目录 Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问前言1.软件安装完成后&#xff0c;打开Everything2.登录cpolar官网 设置空白数据隧道3.将空白数据隧道与本地Everything软件结合起来总结 &a…

Cesium 模型视角锁定(entity)

需求&#xff1a; 需要将视角锁定在以模型为中心&#xff0c;无论怎么旋转和缩放&#xff0c;都是以模型为中心点的。 方法&#xff1a; //绑定方式 viewer.trackedEntity entity; //解绑方式 viewer.trackedEntity undefined;例子 var model_entity viewer.entities.add…