PyQt4在TextEdit控件中创建右键菜单

来源:互联网 发布:ios 存储数组 编辑:程序博客网 时间:2024/05/17 09:08

今天开发界面遇到一个问题,想将textedit的显示内容及时清空,但是由于系统自带的菜单没有清空功能,就需要自己添加该部分内容。

查了很多资料:

大致分为两种方法:

1.一种是修改父窗口Widget的menu方法,添加整体的右键菜单,然后继承父类;通过捕捉右击鼠标的动作设定响应函数。

2.第二种是重写子类的右键菜单,但是需要设定两个参数:

self.textBrowser.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
 self.textBrowser.customContextMenuRequested.connect(self.showTextContextMe)

CustomContextMenu:保持通用菜单设置;

customContextMenuRequested:当有右击鼠标的动作时,弹出菜单,

showTextContextMe:显示位置函数


实际编程中,存在矛盾,如果完全继承父类菜单,修改子类菜单时需要重新设定父类菜单的功能,实现起来比较繁琐;

但是菜单内容可以自己设置。


编写位置显示函数时遇到以下效果区别:

方法一:

      #将菜单在当前位置显示       
#        self.TextContextMenu.move(QtGui.QCursor.pos()) 
#        self.TextContextMenu.show()  
     方法二:
        #在当前坐标下显示,但是菜单停止不走动
        self.TextContextMenu.exec_(QtGui.QCursor.pos())        
        
        #将菜单在右上方显示
#        self.TextContextMenu.move(self.pos() + pos)  


以下是参考的内容,转载过来作为标记:

转自:http://blog.csdn.net/yuanzhangmei1/article/details/7724077



最近在看C++ GUI  Qt4部分其中有个例子对于扩展一个应用程序提供一个上下文菜单,其中该程序只是定义一个变量来实现其中用到了一个函数(下文会给予解答)。但是更高级的是重新定义事件处理函数void contextMenuEvent(QContextMenuEvent *event)。下面讲解其contextMenuEvent(QContextMenuEvent *event)。

 

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 )函数。

例子(该例子即是我改写的)

[cpp] view plaincopyprint?
  1. <span style="font-size:18px;">void MainWindow::contextMenuEvent(QContextMenuEvent *event)  
  2. {  
  3.   
  4.     Context = new QMenu();  
  5.     Context->addAction(ui->actionCut);  
  6.     Context->addAction(ui->actionCope);  
  7.     Context->addAction(ui->actionPase);  
  8.     spreadsheet->setContextMenuPolicy(Qt::DefaultContextMenu);  
  9.     Context->exec(QCursor::pos());  
  10. }</span>  

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


此外还有一篇文章:


http://blog.sina.com.cn/s/blog_7c4674df0100xnmu.html

pyqt 创建右键菜单

(2012-01-26 19:05:21)
转载
标签:

杂谈

分类: Python
  1. #coding=utf-8  
  2.   
  3. import sys  
  4.   
  5. from PyQt4 import QtGui  
  6. from PyQt4.QtCore import Qt  
  7.   
  8. class MainWindow(QtGui.QMainWindow):  
  9.     def __init__(self):  
  10.         super(MainWindow, self).__init__()  
  11.         self.createContextMenu()  
  12.   
  13.   
  14.     def createContextMenu(self):  
  15.         ''''' 
  16.         创建右键菜单 
  17.         '''  
  18.         必须将ContextMenuPolicy设置为Qt.CustomContextMenu  
  19.         否则无法使用customContextMenuRequested信号  
  20.         self.setContextMenuPolicy(Qt.CustomContextMenu)  
  21.         self.customContextMenuRequested.connect(self.showContextMenu)  
  22.   
  23.         创建QMenu  
  24.         self.contextMenu QtGui.QMenu(self 
  25.         self.actionA self.contextMenu.addAction(u'动作A' 
  26.         self.actionB self.contextMenu.addAction(u'动作B' 
  27.         self.actionC self.contextMenu.addAction(u'动作C' 
  28.         将动作与处理函数相关联  
  29.         这里为了简单,将所有action与同一个处理函数相关联,  
  30.         当然也可以将他们分别与不同函数关联,实现不同的功能  
  31.         self.actionA.triggered.connect(self.actionHandler)  
  32.         self.actionB.triggered.connect(self.actionHandler)  
  33.         self.actionB.triggered.connect(self.actionHandler)  
  34.   
  35.   
  36.     def showContextMenu(selfpos):  
  37.         ''''' 
  38.         右键点击时调用的函数 
  39.         '''  
  40.         菜单显示前,将它移动到鼠标点击的位置  
  41.         self.contextMenu.move(self.pos() pos)  
  42.         self.contextMenu.show()  
  43.   
  44.   
  45.     def actionHandler(self):  
  46.         ''''' 
  47.         菜单中的具体action调用的函数 
  48.         '''  
  49.         print 'action handler'  
  50.   
  51.   
  52. if __name__=='__main__' 
  53.     app QtGui.QApplication(sys.argv)  
  54.     window MainWindow()  
  55.     window.show()  
  56.     sys.exit(app.exec_())  

QListWidget 对象的创建这里不在阐述。本文以载入UI为实例

# -*- coding: utf-8 -*-

from PyQt4 import QtCore, QtGui, uic
from PyQt4.QtCore import pyqtSignature

class Ui_formDialog(QtGui.QDialog):

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self)
        uic.loadUi("
form.ui", self)        #form.ui QT界面文件QListWidget对象名为 listView1
        self.
listDataBind()                  #添加QListWidgetItme
        self.
listView1.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)   #定义右键菜单
        
    def 
listDataBind(self):
        item = ['OaK','Banana','Apple','Orange','Grapes','Jayesh']
        for lst in item:
            self.
listView1.addItem(QtGui.QListWidgetItem(lst))
   

    #激活菜单事件
   @pyqtSignature("QPoint")
    def on_
listView1_customContextMenuRequested(self, point):
        item = self.
listView1.itemAt(point)
        #
空白区域不显示菜单
        if item != None:

           self.rightMenuShow()


    #
创建右键菜单
    def rightMenuShow(self):
        rightMenu = QtGui.QMenu(self.
listView1)
        removeAction = QtGui.QAction(u"
删除", self, triggered=self.close)       # triggered为右键菜单点击后的激活事件。这里slef.close调用的是系统自带的关闭事件。
        rightMenu.addAction(removeAction)
        
        addAction = QtGui.QAction(u"
添加", self, triggered=self.addItem)       #也可以指定自定义对象事件
        rightMenu.addAction(addAction)
        rightMenu.exec_(QtGui.QCursor.pos())
       

    def addItem(self):
        pass




0 0
原创粉丝点击