Skip to main content
 首页 » 编程设计

python之如何在左键单击时显示 QMenu

2025年05月04日13fff_TT

QMenu 显示在 QLineEdit 右键单击​​上。 问题:如何修改此代码以在单击鼠标左键时也显示菜单?

from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
import sys 
 
class MyWindow(QWidget): 
    def __init__(self, *args): 
        QWidget.__init__(self, *args) 
 
    def actionFunct(self, argBool): 
        print 'actionFunct()', argBool 
 
    def buildGUI(self): 
        self.line=QLineEdit(self) 
        self.line.setText('My Line Edit')       
 
        self.menu=QMenu(self.line) 
 
        self.line.installEventFilter(self) 
        self.menu.installEventFilter(self) 
 
        for i in range(3): 
            actn=QAction('Action 0%s'%i, self.menu, checkable=True) 
            actn.triggered.connect(self.actionFunct) 
            self.menu.addAction(actn) 
 
        self.line.setContextMenuPolicy(Qt.CustomContextMenu) 
        self.line.connect(self.line, SIGNAL("customContextMenuRequested(QPoint)" ), self.lineClicked) 
 
        layout=QVBoxLayout(self) 
        layout.addWidget(self.line) 
        self.setLayout(layout) 
 
    def lineClicked(self, QPos): 
        print 'lineClicked', QPos 
        parentPosition = self.line.mapToGlobal(QPoint(0, 0))         
        menuPosition = parentPosition + QPos 
 
        self.menu.move(menuPosition) 
        self.menu.show()  
 
if __name__ == "__main__": 
    app = QApplication(sys.argv) 
    w = MyWindow() 
    w.buildGUI() 
    w.show() 
    sys.exit(app.exec_()) 

请您参考如下方法:

解决方案 # 1(感谢 Brendan Abel)。

使用installEventFilter() 方法通过易于定制的eventFilter() 方法路由所有lineedit 事件:

self.line.installEventFilter(self) 

现在所有事件 self.line 触发器都将通过 eventFilter。我们使用接收到的 event 对象查询位置:

event.pos() 

我们将其作为参数发送给 leftClicked() 方法(lineeidit 的右键单击会调用相同的方法)。 从 PyQt4.QtCore 导入 * 从 PyQt4.QtGui 导入 * 导入系统

class MyWindow(QWidget): 
    def __init__(self, *args): 
        QWidget.__init__(self, *args) 
 
    def actionFunct(self, argBool): 
        print 'actionFunct()', argBool 
 
    def buildGUI(self): 
        self.line=QLineEdit(self) 
        self.line.setText('My Line Edit')       
        self.line.installEventFilter(self) 
 
        self.menu=QMenu(self.line) 
 
        for i in range(3): 
            actn=QAction('Action 0%s'%i, self.menu, checkable=True) 
            actn.triggered.connect(self.actionFunct) 
            self.menu.addAction(actn) 
 
        self.line.setContextMenuPolicy(Qt.CustomContextMenu) 
        self.line.connect(self.line, SIGNAL("customContextMenuRequested(QPoint)" ), self.leftClicked) 
 
        self.line.cursorPositionChanged.connect(self.leftClicked) 
 
        layout=QVBoxLayout(self) 
        layout.addWidget(self.line) 
        self.setLayout(layout) 
 
 
    def eventFilter(self, widget, event): 
        print 'eventFilter', widget, event 
        if widget == self.line and isinstance(event, QMouseEvent) and event.buttons() & Qt.LeftButton: 
            self.leftClicked(event.pos()) 
            return True 
        return False 
 
    def leftClicked(self, QPos): 
        print 'leftClicked', QPos 
        parentPosition = self.line.mapToGlobal(QPoint(0, 0))         
        menuPosition = parentPosition + QPos 
 
        self.menu.move(menuPosition) 
        self.menu.show()  
 
if __name__ == "__main__": 
    app = QApplication(sys.argv) 
    w = MyWindow() 
    w.buildGUI() 
    w.show() 
    sys.exit(app.exec_()) 

解决方案#2

首先将QLineEdit 最容易触发的cursorPositionChanged 信号连接到一个方法。 当左键单击时调用此方法使用 Qt 的 QCursor.pos() 查询当前鼠标光标位置:

current_mouse_cursor=QCursor.pos() 

返回类似的东西:

QtCore.QPoint(852, 595) 

最后将菜单移动到查询到的鼠标光标位置并显示:

    self.menu.move(current_mouse_cursor) 
    self.menu.show()  

下面发布了一个工作代码:

from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
import sys 
 
class MyWindow(QWidget): 
    def __init__(self, *args): 
        QWidget.__init__(self, *args) 
 
    def actionFunct(self, argBool): 
        print 'actionFunct()', argBool 
 
    def buildGUI(self): 
        self.line=QLineEdit(self) 
        self.line.setText('My Line Edit')       
 
        self.menu=QMenu(self.line) 
 
        for i in range(3): 
 
            actn=QAction('Action 0%s'%i, self.menu, checkable=True) 
            actn.triggered.connect(self.actionFunct) 
            self.menu.addAction(actn) 
 
        self.line.setContextMenuPolicy(Qt.CustomContextMenu) 
        self.line.connect(self.line, SIGNAL("customContextMenuRequested(QPoint)" ), self.rightClicked) 
 
        self.line.cursorPositionChanged.connect(self.leftClicked) 
 
        layout=QVBoxLayout(self) 
        layout.addWidget(self.line) 
        self.setLayout(layout) 
 
 
    def leftClicked(self, arg): 
        print 'leftClicked', arg, QCursor.pos() 
        self.menu.move(QCursor.pos()) 
        self.menu.show()  
 
    def rightClicked(self, QPos): 
        print 'rightClicked', QPos 
        parentPosition = self.line.mapToGlobal(QPoint(0, 0))         
        menuPosition = parentPosition + QPos 
 
        self.menu.move(menuPosition) 
        self.menu.show()  
 
if __name__ == "__main__": 
    app = QApplication(sys.argv) 
    w = MyWindow() 
    w.buildGUI() 
    w.show() 
    sys.exit(app.exec_())