QT右键菜单的创建及相关问题解决

Qt中添加右键菜单 如果想要在某一窗口中显示右键菜单,其处理方式大体上有两种,分别是基于鼠标事件实现和基于窗口菜单策略实现。其中第二种方式中又有三中国不同的实现方式,因此如果想要在窗口中显示一个右键菜单一共四种实现方式。 阅读详情
 

QWidget及其子类都可有右键菜单,因为QWidget有以下两个与右键菜单有关的函数:

Qt::ContextMenuPolicy contextMenuPolicy () const

void setContextMenuPolicy ( Qt::ContextMenuPolicy policy )

Qt::ContextMenuPolicy枚举类型包括:Qt::DefaultContextMenu, Qt::NoContextMenu, Qt::PreventContextMenu, Qt::ActionsContextMenu, and Qt::CustomContextMenu。

使用方式如下:


1)默认是Qt::DefaultContextMenu。
它是利用右键菜单事件contextMenuEvent()来处理(which means the contextMenuEvent() handler is called)。就是要重写contextMenuEvent( QContextMenuEvent * event )函数。


2)使用Qt::CustomContextMenu。
它是发出QWidget::customContextMenuRequested信号,注意仅仅只是发信号,意味着要自己写显示右键菜单的slot。
这个信号是QWidget唯一与右键菜单有关的信号(也是自有的唯一信号),同时也是很容易被忽略的signal:

void customContextMenuRequested ( const QPoint & pos )

该信号的发出条件是:用户请求contextMenu(常规就是鼠标右击啦)且同时被击的widget其contextMenuPolicy又是Qt::CustomContextMenu。
注意:pos是该widget接收右键菜单事件的位置,一般是在该部件的坐标系中。但是对于QAbstratScrollArea及其子类例外,是对应着其视口viewport()的坐标系。如常用的QTableView、QHeaderView就是QAbstratScrollArea的子类。
因为仅发信号,所以需自己写显示右键菜单的slot来响应,例如一个表格(QTableView类型)表头的显示右键菜单槽:
datatable->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(datatable->horizontalHeader(), SIGNAL(customContextMenuRequested(const QPoint&)),
        this, SLOT(show_contextmenu(const QPoint&)));//this是datatable所在窗口
QMenu *cmenu = NULL;
show_contextmenu(const QPoint& pos)
{
    if(cmenu)//保证同时只存在一个menu,及时释放内存
    {
        delete cmenu;
        cmenu = NULL;
    }
    QMenu cmenu = new QMenu(datatable->horizontalHeader());
   
    QAction *ascendSortAction = cmenu->addAction("升序");
    QAction *descendSortAction = cmenu->addAction("降序");
    QAction *filterAction = cmenu->addAction("过滤");
    QAction *reshowAction = cmenu->addAction("重载");
   
    connect(ascendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_ascend()));
    connect(descendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_descend()));
    connect(filterAction, SIGNAL(triggered(bool)), this, SLOT(show_filter_dlg()));
    connect(reshowAction, SIGNAL(triggered(bool)), this, SLOT(reshow_data()));
   
    cmenu->exec(QCursor::pos());//在当前鼠标位置显示
    //cmenu->exec(pos)是在viewport显示
}

也可先做好cmenu,好处是始终使用一个:
    QMenu cmenu = new QMenu(datatable->horizontalHeader());
   
    QAction *ascendSortAction = cmenu->addAction("升序");
    QAction *descendSortAction = cmenu->addAction("降序");
    QAction *filterAction = cmenu->addAction("过滤");
    QAction *reshowAction = cmenu->addAction("重载");
   
    connect(ascendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_ascend()));
    connect(descendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_descend()));
    connect(filterAction, SIGNAL(triggered(bool)), this, SLOT(show_filter_dlg()));
    connect(reshowAction, SIGNAL(triggered(bool)), this, SLOT(reshow_data()));
show_contextmenu(const QPoint& pos)
{
    if(cmenu)
    {
        cmenu->exec(QCursor::pos());
    }
}


3)使用Qt::ActionsContextMenu。
把部件的所有action即QWidget::actions()作为context menu显示出来。
还是上面的例子,要在表格(QTableView类型)表头显示右键菜单:
        QAction *ascendSortAction = new QAction("升序", this);
        QAction *descendSortAction = new QAction("降序", this);
        QAction *filterAction = new QAction("过滤", this);
        QAction *unfilterAction = new QAction("取消过滤", this);
   
        connect(ascendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_ascend()));
        connect(descendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_descend()));
        connect(filterAction, SIGNAL(triggered(bool)), this, SLOT(filter_table()));
        connect(unfilterAction, SIGNAL(triggered(bool)), this, SLOT(unfilter_table()));
   
        datatable->horizontalHeader()->addAction(ascendSortAction);
        datatable->horizontalHeader()->addAction(descendSortAction);
        datatable->horizontalHeader()->addAction(filterAction);
        datatable->horizontalHeader()->addAction(unfilterAction);
        
        datatable->horizontalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu);

另外两个就是不显示context menu了:
Qt::NoContextMenu
    the widget does not feature a context menu, context menu handling is deferred to the widget's parent.
   
Qt::PreventContextMenu
    the widget does not feature a context menu, and in contrast to NoContextMenu, the handling is not deferred to the widget's parent. This means that all right mouse button events are guaranteed to be delivered to the widget itself through mousePressEvent(), and mouseReleaseEvent().

补充:
    使用Qt::ActionsContextMenu比较简洁,但是如果需要根据当前菜单弹出的位置来定义不同菜单,或者像上个例子,在表格(QTableView类型)表头显示右键菜单时,我需要知道是哪一列表头被点击,从而在后来调用sort_ascend()排序函数时能够根据不同列进行不同排序策略,那么Qt::ActionsContextMenu就做不到了。
    这种需要捕捉弹出位置的情况只好用Qt::ActionsContextMenu了,customContextMenuRequested ( const QPoint & pos )信号返回点击位置pos(在表头视口坐标系中位置),然后表头即可调用logicalIndexAt(pos)函数得到被点击section对应的index即被点击部分的列号,然后存下来可供后面action激活的排序槽使用。
show_contextmenu(const QPoint& pos)
{
    //get related column of headerview
    contextmenu_column = datatable->horizontalHeader()->logicalIndexAt(pos);

    //show contextmenu
    if(cmenu)
    {
        cmenu->exec(QCursor::pos());
    }
}

 

【相关问题】

1.问题:当把 QTreeWidget 放在别的 QWidget 中以后,发现右键总是捕捉不到最下面的一个Item 节点。

错误代码:

void ShowItems::contextMenuEvent ( QContextMenuEvent * event )

{
    QPoint p = tree->mapFromGlobal(QCursor::pos());
    if(tree->itemAt(p) != NULL)
    {
        QMenu* popMenu = new QMenu(this);
        popMenu->addAction(insertItemAction);
        popMenu->addAction(deleteItemAction);
        popMenu->exec(QCursor::pos());
    }
}

原因:我们认为的(0,0)点的坐标与实际的有差距

解决:使用viewport()返回的QWidget作为当前的坐标QWidget

QWidget * QAbstractScrollArea::viewport () const

修改后,代码:

void ShowItems::contextMenuEvent (QContextMenuEvent *event )

{
    QWidget *w = tree->viewport();
    QPoint p = w->mapFromGlobal(QCursor::pos());
    if(tree->itemAt(p) != NULL)
    {
        QMenu* popMenu = new QMenu(this);
        popMenu->addAction(insertItemAction);
        popMenu->addAction(deleteItemAction);
        popMenu->exec(QCursor::pos());
    }
}

 

QT添加右键菜单(二):QWidget的右键菜单策略 使用QWidget的上下文菜单策略实现右键菜单,并对QWidget的上下文菜单策略的使用方法进行介绍。 阅读详情

相关推荐

QTableWidget添加右键菜单的详细过程

包含头文件: #include <QMenu> #include <QAction> 在类定义中增加一个QMenu对象指针: QMenu *table_widget_menu; 在父窗体构造函数中允许QTableWidget接收QWidget::customContextMenuRequested()信号。 ui->tableWidget...

hyafz的专栏 1万+

QContextMenuEvent 是 Qt 框架中的一个类,用于表示上下文菜单事件

上下文菜单事件(Context Menu Event)在用户右击部件时触发,通常用于显示上下文菜单。这些菜单可以包含与所选部件相关的操作和选项。获取鼠标右击的全局位置。最后,根据用户选择的菜单项进行相应的处理。类提供了获取上下文菜单事件的相关信息的功能。函数,以处理上下文菜单事件。在函数中,我们创建了一个。是 Qt 框架中的一个类,用于表示上下文菜单事件。类,并添加了一些额外的成员函数和属性。对象,并添加了两个菜单项。在上述示例中,我们重写了部件类的。函数显示菜单,并通过。

m0_46376834的博客 1887

实例QT程序 —— QTableWidget 表格右键菜单功能(该方式可用于任意Widget子类控件)

目录 1.简介 2.效果图 3.重点讲解 4.源码 1.简介 本文主要介绍了在QTableWidget表格中如何添加右键菜单功能及相关重点讲解,并有动态效果图展示方便用于查看实际效果功能。 回目录 2.效果图 运行效果图 回目录 3.重点讲解 1.)通过UI设计器选中控件添加右键菜单的槽函数。 操作方式如下图所示 : 右键添加“右键菜单”槽函数 2) 增加右键菜单...

Redboy_Crazy的专栏 9771

Qt实现右键菜单

其中,重写contextMenuEvent函数更适合在需要弹出右键菜单的窗口较少的情况下使用,而使用QMenu和QAction则更加灵活,适合在任意窗口中使用。然后调用QMenu的exec函数来弹出右键菜单。在需要弹出右键菜单的窗口中,我们可以将需要显示的QAction类别组织成QMenu对象,并在鼠标右键按下事件中调用QMenu的exec函数来弹出右键菜单。我们可以通过重写该函数,在需要弹出右键菜单的时候,创建QMenu和QAction,并且将QAction添加到QMenu中,最后弹出QMenu

2301_79325339的博客 2708

详解Qt QContextMenuEvent、QDragEnterEvent、QDragMoveEvent与QDropEvent

在现代应用程序开发中,用户体验至关重要,而事件处理是提升用户交互性的关键所在。Qt 是一个功能强大的跨平台应用框架,它提供了丰富的事件处理机制,使开发者能够轻松实现复杂的用户交互功能。在众多事件类型中,QContextMenuEvent、QDragEnterEvent、QDragMoveEvent 和 QDropEvent 是处理上下文菜单和拖放操作的重要事件类型。本文将详细介绍这些事件的功能和使用方法,帮助开发者更好地理解和应用这些事件处理机制,从而构建出更为流畅和直观的用户界面。

m0_62599305的博客 892

Qt右键菜单及位置捕捉问题

这个是原文:http://hi.baidu.com/%B7%C9%CF%E8_%C6%D1%B9%AB%D3%A2/blog/item/802a999a8625debdc9eaf423.html2009年04月24日 星期五 21:18QWidget及其子类都可有右键菜单,因为QWidget有以下两个与右键菜单有关的函数:Qt::ContextMenuPolicy co

iotplan.com 物联网技术专栏 2383

Qt事件之创建鼠标右击菜单【上下文菜单事件-----contextMenuEvent() 】

在窗口中古创建一个右击菜单步骤: 1. 重写上下文菜单事件–contextMenuEvent(QContextMenuEvent * event); void MyWidget::contextMenuEvent(QContextMenuEvent * event) { m_rightClieckMenu->exec(QCursor::pos()); //QCursor::pos()获取...

愤怒的狸猫 的博客 3081

解决Qt工程UI内menuBar、mainToolBar、dockWidget右键上下文菜单无法关闭的问题

程序运行时,在menuBar或mainToolBar区域内单击鼠标右键,会出现一个默认的上下文菜单,并且有一个空白的action(如果添加了dockWidget,也会出现这种情况)注意:槽函数最好不要只写一个分号。点击该action,会发现mainToolBar被隐藏了,因此这个action正是默认的那个mainToolBar。有时不需要这些上下文菜单,空白的action也会造成误解和干扰,那么应该怎样隐藏它们呢?修改后,问题解决右键不会出现空的上下文菜单,关闭成功。

qq_41424539的博客 475

Qt创建右键菜单的方法

函数 所有派生自QWidget的控件,若实现在其上右键单击弹出菜单,需要设置该控件的上下文菜单策略函数为setContextMenuPolicy(Qt::CustomContextMenu),设置该策略后当用户右键点击控件时qt会发送一个信号customContextMenuRequested() ,给这个信号设置相应的槽函数,在槽函数中将菜单展示出来就行了。 涉及相关函数其原型如下: void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy po

u011555996的博客 7230

Qt窗口中添加右键菜单

qt中添加右键菜单

记录我目之所及的世界 2883

Qt教程08】在Qt窗口中添加右键菜单

原创作者:郑同学的笔记原创地址:https://zhengjunxue.blog.csdn.net/article/details/137136773qq技术交流群:921273910。

junxuezheng的博客 1726

Qt基础:右键菜单

Qt 窗口右键菜单实现:4种方式

qingttqing的博客 1142

【十六】【QT开发应用】Menu菜单,contextMenuEvent,setContextMenuPolicy,addAction

Qt 框架中,QMenu 类用于创建和管理菜单菜单是用户界面的一部分,可以包含多个选项或动作,用户可以选择这些选项来执行特定的功能。菜单通常显示菜单栏、上下文菜单右键菜单)或工具栏中。基本用法添加动作:使用 addAction 方法将 QAction 对象添加到菜单中。QAction 代表菜单中的一个选项或动作。显示菜单:菜单可以在指定的位置显示,例如在鼠标光标位置。

m0_74163972的博客 1502

QT开发笔记-基础篇】| 第四章 事件QEvent | 4.9 右键菜单事件

常用事件讲解 详解事件传递流程 小案例-无边框窗口

B站-大轮明王讲Qt 1966

qt右键菜单的两种方式----contextMenuEvent+customContextMenuRequested

来源:微信公众号「编程学习基地」 文章目录qt右键菜单 qt右键菜单 第一步 准备菜单 //定义菜单 QMenu *RightButtonMenu; //右键菜单 QAction *saveSreenShot; //保存到粘贴板 QAction *saveCopyAs; //另存为 QAction *quitSreenShot; //退出截图 初始化菜单 saveSreenShot = new QAction(tr("保存截图"), this); //connect(saveSreenSho..

deroy 6443

QT右键菜单的建立步骤

右键菜单在一个项目中是必不可少的组件,在QT中的使用可能要比VS中使用复杂一些,尤其在QT中貌似只能用代码来实现。所以我们把建立右键菜单和绑定对应的事件,也就是从建立到使用逐步介绍给大家。

河西~石头 2304

Qt上下文菜单右键菜单)的几种方式,setContextMenuPolicy(Qt::ContextMenuPolicy policy)函数5个参数的用法

设置右健菜单的方法原型:void setContextMenuPolicy(Qt::ContextMenuPolicy policy),参数有5个枚举值,说明如下: 序号 值 说明 1 Qt::NoContextMenu 小部件没有上下文菜单,上下文菜单的处理被推迟到小部件的父级 2 Qt::PreventContextMenu 该小部件没有上下文菜单,与NoContextMenu相反,处理不会被推迟到小部件的父级。所有鼠标右键事件都保证通过void QAbstractItemView:

mabiao0825的博客 1万+

contextMenuEvent

【代码】contextMenuEvent。

hw5230的博客 522
上一篇: QT QTableWidget 用法总结
下一篇: QT SQL 语句相关的返回处理
polokang
博客等级 码龄24年 38粉丝 16原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值