【问题标题】:How to show QMenu on left click如何在左键单击时显示 QMenu
【发布时间】:2015-03-19 05:35:12
【问题描述】:

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

【问题讨论】:

    标签: python qt pyqt qlineedit qmenu


    【解决方案1】:

    解决方案 #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_())
    

    【讨论】:

    • cursorPositionChanged 被触发除了鼠标左键单击之外的其他事件。当输入 lineedit 以及使用箭头键移动光标时也会触发它。
    【解决方案2】:

    您需要在 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
    

    【讨论】:

    • 感谢您的建议!
    猜你喜欢
    • 2011-04-04
    • 2018-01-29
    • 2013-01-18
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多