在Qt窗口中添加右键菜单

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小程序中通过canvas生成并保存图片

1. html <canvas class"canvas" id"photo" type"2d" style"width:200px;height: 300px;"></canvas> <button bindtap"saveImage">保存</button> <!-- 用来展示生成的那张图片 --> <image…

js判断用户当前网络状态和判断网速

前端判断用户当前网络状态和判断网速 一、第一种是通过 HTML5 提供的 navigator 去检测网络(1)、原理介绍:(2)、兼容性 二、监听window.ononline和window.onoffline事件:三、通过ajax进行请求判断(兼容性好-推荐)(1)、原理介绍:(2)、注意: 四、navigator.connection方法监听网络…

Quartz任务调度框架介绍和使用

一、Quartz介绍 Quartz [kwɔːts] 是OpenSymphony开源组织在Job scheduling领域又一个开源项目&#xff0c;完全由Java开发&#xff0c;可以用来执行定时任务&#xff0c;类似于java.util.Timer。但是相较于Timer&#xff0c; Quartz增加了很多功能&#xff1a; 1.持久性作业 …

小区新冠疫情管理系统的设计与实现/基于springboot的小区疫情管理系统

摘要 采用更加便于维护和使用的Java语言&#xff0c;其可拓展性高且更富于表现力&#xff0c;基于mysql数据库、Springboot框架开发的小区新冠疫情管理系统&#xff0c;方便用户查看物资信息、疫苗信息。通过Eclipse来进行网页编程&#xff0c;其方便易用、移植适用性广、更加安…

Can‘t find end of central directory : is this a zip file ? at XMLHttpRequest

导出woed出现这个报错,原因其实很简单,路径写错了, 这个word首先必须是docx格式,然后必须放在public文件包下 如果放在public文件包下还没有用,则放在public包下 参考帖子: https://www.cnblogs.com/hejun26/p/13647927.html

渗透率超90%!智能座舱赛道迎来「存量」替代升级大周期

智能座舱赛道&#xff0c;正在迎来新一轮芯片替代潮。 相比于智能驾驶领域&#xff0c;座舱主机芯片市场并不「性感」&#xff0c;但巨大的存量替代升级机会&#xff0c;也不容小视。 高工智能汽车研究院监测数据显示&#xff0c;2023年1-6月中国市场&#xff08;不含进出口&am…

【Linux操作系统】Linux系统编程中信号捕捉的实现

在Linux系统编程中&#xff0c;信号是一种重要的机制&#xff0c;用于实现进程间通信和控制。当某个事件发生时&#xff0c;如用户按下CtrlC键&#xff0c;操作系统会向进程发送一个信号&#xff0c;进程可以捕获并相应地处理该信号。本篇博客将介绍信号的分类、捕获与处理方式…

什么是有效的预测性维护 ?

在现代制造业的背景下&#xff0c;设备的可靠性和生产效率成为了企业追求的关键目标。而预测性维护&#xff08;Predictive Maintenance&#xff0c;简称PdM&#xff09;作为一种先进的维护策略&#xff0c;逐渐成为了实现这些目标的重要工具。然而&#xff0c;什么是有效的预测…

Windows wsl2支持systemd

背景 很多Linux发行版都是使用systemd来管理程序进程&#xff0c;但是在WSL中默认是用init来管理进程的。 为了符合长久的使用习惯&#xff0c;且省去不必要的学习成本&#xff0c;就在WSL的发行版&#xff08;我这里安装的是Ubuntu20.04&#xff09;中支持systemd&#xff0…

计算机视觉 -- 图像分割

文章目录 1. 图像分割2. FCN2.1 语义分割– FCN &#xff08;Fully Convolutional Networks&#xff09;2.2 FCN--deconv2.3 Unpool2.4 拓展–DeconvNet 3. 实例分割3.1 实例分割--Mask R-CNN3.2 Mask R-CNN3.3 Faster R-CNN与 Mask R-CNN3.4 Mask R-CNN&#xff1a;Resnet1013…

常用的Selenium基础使用模板和简单封装

前言 近来又用上了 Selneium &#xff0c;因为反复用到&#xff0c;所以在这里将一些常用的方法封装起来&#xff0c;方便后续的使用。 在这篇文章中&#xff0c;我们将探讨 Selenium 的基础模板和基础封装&#xff0c;以便更好地理解 Selenium 的使用方法。 在Selenium的使…

web---Vue2_语法学习

文章目录 1、Vue2 常用指令1.1 初始Vue1.2 Vue的两种模板语法1.3 数据绑定1.4 el和data的两种写法1.5 MVVM模型1.6 Vue中的数据代理1.7 事件处理--事件的基本使用1.7 事件处理--事件修饰符1.7 事件处理--键盘事件1.8 计算属性1.9 监视属性1.9 深度监视2.0 绑定css样式2.1 条件渲…

spring复习:(57)PropertyOverrideConfigurer用法及工作原理

一、属性配置文件 dataSource.urljdbc:mysql://xxx.xxx.xxx.xxx/test dataSource.usernameroot dataSource.passwordxxxxxx dataSource.driverClassNamecom.mysql.jdbc.Driver #dataSource.typecom.alibaba.druid.pool.DruidDataSource二、spring配置文件 <?xml version&…

NPM 管理组织成员

目录 1、向组织添加成员 1.1 邀请成员加入您的组织 1.2 撤销组织邀请 2、接收或拒接组织邀请 2.1 接收组织邀请 2.2 拒绝组织邀请 3、组织角色和权限 4、管理组织权限 5、从组织中删除成员 1、向组织添加成员 作为组织所有者&#xff0c;您可以将其他npm用户添加到…

[保研/考研机试] KY212 二叉树遍历 华中科技大学复试上机题 C++实现

题目链接&#xff1a; 二叉树遍历_牛客题霸_牛客网二叉树的前序、中序、后序遍历的定义&#xff1a; 前序遍历&#xff1a;对任一子树&#xff0c;先访问根&#xff0c;然后遍历其左子树&#xff0c;最。题目来自【牛客题霸】https://www.nowcoder.com/share/jump/43719512169…

【仿写tomcat】六、解析xml文件配置端口、线程池核心参数

线程池改造 上一篇文章中我们用了Excutors创建了线程&#xff0c;这里我们将它改造成包含所有线程池核心参数的形式。 package com.tomcatServer.http;import java.util.concurrent.*;/*** 线程池跑龙套** author ez4sterben* date 2023/08/05*/ public class ThreadPool {pr…

php 系列题目,包含查看后端源代码

一、弱类型比较问题 原则&#xff1a; 1.字符串和数字比较&#xff0c;字符串回被转换成数字。 "admin" 0&#xff08;true) admin被转换成数字&#xff0c;由于admin是字符串&#xff0c;转换失败&#xff0c;变成0 int(admin)0,所以比较结果是ture 2.混合字符串转…

RabbitMq的使用

最近处理访客记录所以&#xff0c;来学习下rabbitMQ。之前同事已经写好了&#xff0c;这里只需要进行消费&#xff0c;后续会逐渐完善。 0.介绍 0.1交换机&#xff08;Exchanges&#xff09; rabbitmq中生产者发送的消息都是发送到交换机&#xff0c;再由交换机推入队列。所…

百度云BOS云存储的图片如何在访问时,同时进行格式转换、缩放等处理

前言 之前做了一个图片格式转换和压缩的服务&#xff0c;结果太占内存。后来查到在访问图片链接时&#xff0c;支持进行图片压缩和格式转换&#xff0c;本来想着先格式转换、压缩图片再上传到BOS&#xff0c;现在变成了上传后&#xff0c;访问时进行压缩和格式转换。想了想&am…

无人机航管应答机 ping200XR

产品概述 ping200XR是一个完整的系统&#xff0c;旨在满足航管应答器和自动相关监视广播(ADS-B)的要求&#xff0c;在管制空域操作无人航空系统(UAS)。该系统完全可配置为模式A&#xff0c;模式C&#xff0c;模式S转发器和扩展ADS-B发射机的任何组合。ping200XR包括一个精度超…