如何在左键单击时显示QMenu

时间:2015-01-20 20:36:44

标签: python qt pyqt qlineedit qmenu

QMenu右键单击显示QLineEdit问题:如何修改此代码以便在左键单击时显示菜单?

enter image description here

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_())

2 个答案:

答案 0 :(得分:4)

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

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

self.line.installEventFilter(self)

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

event.pos()

我们将leftClicked()方法作为参数发送(在lineeidit' s右键单击时调用相同的方法)。     来自PyQt4.QtCore import *     来自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.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' s QCursor.pos()

current_mouse_cursor=QCursor.pos()

返回类似的内容:

QtCore.QPoint(852, 595)

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

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

enter image description here

下面张贴了一份工作代码:

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_())

答案 1 :(得分:3)

您需要在Window类上定义eventFilter方法以过滤/处理事件。

def eventFilter(self, obj, event):
    if obj == self.line and isinstance(event, QMouseEvent) and event.buttons() & Qt.LeftButton:
        self.lineClicked(event.pos())
        return True
    return False