PyQt4在TextEdit控件中創建右鍵菜單

今天開發界面遇到一個問題,想將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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章