当前位置: 首页 > news >正文

在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_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic: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.lryc.cn/news/135212.html

相关文章:

  • Day8 智慧商城
  • LeetCode:Hot100python版本之回溯
  • 分布式事务理论基础
  • 线性代数强化第三章
  • 搭建自己的私有 开源LoRaWAN 网络服务器(The ThingsStack)---之配置
  • 多维时序 | MATLAB实现SCNGO-CNN-Attention多变量时间序列预测
  • clickhouse的删除和更新
  • 微前端 - qiankun
  • 前端编辑页面修改后和原始数据比较差异
  • docker第一次作业
  • Springboot3.0.0+集成SpringDoc并配置knife4j的UI
  • 电脑运行缓慢?4个方法,加速电脑运行!
  • 3.Docker 搭建 MySQL8.0
  • Mybatis的SqlSource SqlNode BoundSql
  • html动态爱心代码【二】(附源码)
  • 【Rust】Rust学习 第十六章无畏并发
  • 系统报错mfc100u.dll丢失的解决方法(完美解决dll问题)
  • docker compose的用法
  • Linux: 使用 ssh 连接其他服务器
  • [.NET/WPF] CommunityToolkit.Mvvm 异步指令
  • 热烈祝贺汇隆成功入选航天系统采购供应商库
  • 2019年3月全国计算机等级考试真题(C语言二级)
  • MySQL 游标
  • ElasticSearch 7.4学习记录(DSL语法)
  • 全志orangepi-zero2驱动编写2,控制电平高低
  • 软考高级系统架构设计师系列之:论文典型试题写作要点和写作素材总结系列文章四
  • 06.利用Redis实现点赞功能
  • 【React】生命周期和钩子函数
  • 无涯教程-TensorFlow - 优化器
  • 基于AQS+双向链表实现队列先进先出