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

原创 2014年08月17日 00:23:23

今天开发界面遇到一个问题,想将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 )函数。

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

  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(self, pos):  
  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




pyqt4,QTableWidget 动态添加控件,添加图片,右键菜单选项

#-*- coding:utf-8 -*- #######line table 使用 from PyQt4.QtCore import * from PyQt4.QtGui import * impo...

如何实时显示内容到TExtEdit控件上

由于PyQt开发执行函数完毕返回结果时是将所有的结果都运行结束了返回,但是这样会有很长的yanchi...

170324 PyQt5-TextEdit的滚动效果

1625-5 王子昂 总结《2017年3月24日》 【连续第174天总结】 A. PyQt5 文本框的预览、滚动效果 B. 预览效果很简单,只需要在输入框内容变化时发出信号,调取槽来改变预览框...

PyQt4 QAction()使用教程

exit=QtGui.QAction(QtGui.QIcon('pix/Moon.bmp'),'Exit',self) #创建一个action "exti"为title self 为parent ...
  • jjwspj
  • jjwspj
  • 2012年09月17日 17:13
  • 3248

Pyqt5右键菜单

右键菜单的位置: self.RightMenu.exec_(QCursor.pos())

Linux下画原理图和PCB

Linux下画原理图和PCB Windows下大名鼎鼎的Allegro和经典的Protel 99SE都是不支持Linux操作系统的,做Linux驱动开发免不了要看一下原理图和PCB。 一般的做法有三种...
  • kangear
  • kangear
  • 2014年12月15日 09:34
  • 7887

介绍2款最流行的画PCB工具

PCB(Printed Circuit Board)设计软件经过多年的发展、不断地修改和完善,或优存劣汰、或收购兼并、或强强联合,现在只剩下Cadence和Mentor两家公司独大。         ...
  • lghtjpu
  • lghtjpu
  • 2010年07月27日 23:21
  • 5536

QT笔记(3)——Qt的lineEdit和textEdit的右键菜单汉化

关于Qt一些控件鼠标右键菜单汉化的问题,网上有一些方法,试了一下,这里做一下总结: 1、汉化需要“.qm”这个文件,这个如果深入的话可以学习一下Qt的Linguist,这个网上很多;如果只做右键菜单汉...

PyQt按钮右键菜单

第一是按钮的自定义,第二是右键菜单的使用,不仅是按钮的右键菜单,其他一些控件的右键菜单也可以类似创建和使用。 关于右键菜单则是QMenu的一些使用方法有:菜单的样式表,右键菜单的创建,右键菜单的显示位...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:PyQt4在TextEdit控件中创建右键菜单
举报原因:
原因补充:

(最多只允许输入30个字)