Qt QTableView 上加右键弹出菜单, 并复制选中的单元格内容到剪贴板中

http://wenku.baidu.com/view/c51cfb63cf84b9d528ea7a29.html

http://www.cppblog.com/biao/archive/2010/01/01/104593.html

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());
    }
}

Qt:QT右键菜单的更多相关文章

  1. (四)Qt之右键菜单

    1.右键菜单创建和显示 作为一种交互性强.使用方便的右键菜单在程序中是非常常用的,在Qt中可以轻松的实现. QMenu menu; //添加菜单项,指定图标.名称.响应函数 menu.addActio ...

  2. QT treewidget 右键菜单

    VS2012+QT5.2 ,没有ui,纯代码实现右键 方法一:常规但略麻烦 1.头文件slot中声明 QTreeWidget *tree; void showrightMenu(QPoint);//显 ...

  3. Qt添加右键菜单

    QAction *hideAction = new QAction(tr(" 隐藏"),this); addAction(hideAction); setContextMenuPo ...

  4. QML添加右键菜单

    MouseArea { id: mouseRegion anchors.fill: parent; acceptedButtons: Qt.LeftButton | Qt.RightButton // ...

  5. Qt之QAbstractItemView右键菜单

    一.功能概述 说起右键菜单,之前Qt之自定义QLineEdit右键菜单这篇文章中我已经讲述过3种右键菜单的实现方式,今儿也是在啰嗦一下,针对QListWidget类在定制一下右键菜单,我使用的具体方式 ...

  6. Qt之自定义QLineEdit右键菜单

    一.QLineEdit说明 QLineEdit是单行文本框,不同于QTextEdit,他只能显示一行文本,通常可以用作用户名.密码和搜索框等.它还提供了一些列的信号和槽,方便我们使用,有兴趣的小伙伴可 ...

  7. Qt——右键菜单

    所谓“右键菜单”,我们可以这样来看:右键+菜单.所以我们可以定义一个菜单,然后重写鼠标点击事件,令菜单在鼠标右击的时候弹出来.这种方法是可以的,但是Qt提供了一种专门用于右键菜单的方法,且看下面这个属 ...

  8. Qt之密码框不可选中、复制、粘贴、无右键菜单等

    简述 在做用户登录.修改密码的时候,往往会用到密码框,其中一些功能要求与普通的输入框不同,例如:不能选中.复制.粘贴.无右键菜单等功能,当然设置密码不可见是必须的! 下面介绍两种方式来实现相同的效果. ...

  9. Qt之国际化(系统文本-QMessageBox按钮、QLineEdit右键菜单等)

    简介 使用Qt的时候,经常会遇到英文问题,例如:QMessageBox中的按钮.QLineEdit.QSpinBox.QScrollBar中的右键菜单等.通常情况下,我们软件都不会是纯英文的,那么如何 ...

  10. 【Qt】Qt之密码框不可选中、复制、粘贴、无右键菜单等【转】

    简述 在做用户登录.修改密码的时候,往往会用到密码框,其中一些功能要求与普通的输入框不同,例如:不能选中.复制.粘贴.无右键菜单等功能,当然设置密码不可见是必须的! 下面介绍两种方式来实现相同的效果. ...

随机推荐

  1. MVC 生成PDf表格并插入图片

    最近做的项目中有一个功能,将最终的个人信息生成PDF表格,并插入图片.对于没接触过的程序员来说回一片茫然,网上有多种生成PDf的方法,我给大家介绍一下我认为比较简单,好操作的一种. iTextShar ...

  2. maven入门程序(3)

    欢迎转载交流:http://www.cnblogs.com/shizhongtao/p/3472864.html 这里我将展示如何用maven快速创建一个基于spring的web框架.创建步骤和上一篇 ...

  3. 你早该这么玩Excel 读书笔记

    1. Excel用来分析数据,至少要有一份原始数据和对于的分类汇总数据,这两种数据在一项任务中,应该是存放在同一个Excel文档中的,在书籍中,把他们叫做源数据表和分类汇总表.用户输入源数据表,根据相 ...

  4. C++对象的JSON序列化与反序列化探索续-复杂对象的序列化与反序列化

    本文是基本上一篇博文进行改进而成,上一篇请见: C++对象的JSON序列化与反序列化探索 此处就不多说了,直接上代码. 1. 序列化基类 #pragma once #include <strin ...

  5. JAVA_SE复习(异常)

    异常.调试和断言 一. 异常的分类 1. 可查异常    例: 2. 不可查异常  例:Runtime Exception 3. 异常的分类结构: 1. 不执行finally 子句的唯一情况是虚拟机关 ...

  6. Java多线程(三) 多线程间的基本通信

    多条线程在操作同一份数据的时候,一般需要程序去控制好变量.在多条线程同时运行的前提下控制变量,涉及到线程通信及变量保护等. 本博文主要总结:①线程是如何通信  ②如何保护线程变量 1.Java里的线程 ...

  7. Winform 异步更新listbox

    public partial class Form1 : Form { private BackgroundWorker bw; public Form1() { InitializeComponen ...

  8. NodeJS + Socket.io聊天服务器连接数达到1024后就连不上了

    如果是亚马逊的Engine Yard服务器,解决办法为: 1.查看端口占用情况,找到nodejs进程号,例如我这里是8000端口 lsof -i:8000  找到pid 例如为 8213 2.设置no ...

  9. [Interview][CodingExam]

    這次去Interview, 其中有一個公司 把我列為 2/25的考慮對象, 在Final 的 1/2, 我被刷掉了. 因為第一輪的程式,我稍微google了一下,參考了既有的寫法. 即使第二輪我用完全 ...

  10. php字符串首字母转换大小写的实例分享

    php中对字符串首字母进行大小写转换的例子. in: 后端程序首字母变大写:ucwords() <?php $foo = 'hello world!'; $foo = ucwords($foo) ...