2

我正在尝试实现一个“打开”按钮,这样如果用户按住它并按住它,就会弹出一个供用户选择的应用程序菜单;但是一旦用户释放鼠标,菜单就会消失。如果用户在未选择菜单上的应用程序的情况下释放鼠标,则应使用默认应用程序打开文件。我将此按钮实现为 aQToolButton并按如下方式连接信号:

self.ui_open_btn.pressed.connect(self._onOpenBtnPressed)
self.ui_open_btn.triggered.connect(self._onOpenBtnTriggered)

def _onOpenBtnPressed(self):
    self.ui_open_btn.showMenu()

def _onOpenBtnTriggered(self, action):
    application_name = action.text()
    # code to launch the application

现在,当用户按下按钮时,将弹出菜单。但是,当用户释放按钮时,菜单仍然存在,并且通过单击它会触发菜单上的操作。DelayedPopup我在和InstantPopup模式下都试过了。只要菜单设置为self.ui_open_btn,我就无法再捕捉到任何released信号。用户释放鼠标时如何隐藏菜单?如何通过释放鼠标来触发菜单上的动作?

- 添加 - -

我发现了另一个关于使用的问题QToolButton:按下按钮时菜单总是弹出。相反,我想捕捉pressed信号,做一些检查以确定菜单是否应该弹出。所以我改变了我的方法,通过子类化QPushButtonQMenu. 请参阅我在下面的答案中提出的代码。

谢谢。

4

2 回答 2

0

创建一个自定义 QToolButton,它将过滤来自菜单的事件,并对菜单接收到的鼠标释放事件做出反应:

class MyToolButton(QtGui.QToolButton):
    def __init__(self, *args):
        QtGui.QToolButton.__init__(self, *args)
    def eventFilter(self, menu, event):
        if event.type() == QtCore.QEvent.MouseButtonRelease:
            if self.underMouse():
                menu.close()
                # and now do default action
                print "doing default action"
                return True
        return False

设置菜单后安装事件过滤器:

self.ui_open_btn.menu().installEventFilter(self.ui_open_btn)
于 2013-10-03T01:31:33.967 回答
0

我设法通过子类化QPushButton和实现了我想要的QMennu

class MyMenu(QtGui.QMenu):
    """ Custom menu which will close when mouse is released. ""'"
    def mouseReleaseEvent(self, event):
        action = self.actionAt(event.pos())
        self.triggered.emit(action)
        self.close()

class MyButton(QtGui.QPushButton):
    triggered = QtCore.pyqtSignal("QAction")

    def __init__(self, menu=None, parent=None):
        super(MyButton, self).__init__(parent)
        self.setMenu(menu)

    def menu(self):
        return self._menu

    def setMenu(self, menu):
        self._menu = menu if menu else MyMenu(self)
        self._menu.triggered.connect(self.triggered.emit)

QDialog包含此按钮中,我执行以下操作:

menu = MyMenu(self)
# insert here code to add actions to menu
self.open_btn = MyButton(parent=self, menu=menu)
self.open_btn.pressed.connect(self._onOpenBtnPressed)
self.open_btn.triggered.connect(self._onOpenBtnTriggered)

def _onOpenBtnPressed(self):
    # insert here code to check whether we should pop up the menu
    pos = self.mapToGlobal(self.open_btn.pos())
    pos.setY(pos.y() + self.open_btn.height())
    self.open_btn.menu().move(pos)
    self.open_btn.menu().show()

def _onOpenBtnTriggered(self, action):
    if action:
        application_name = str(action.text())
        # insert here code to launch this application
    else:
        # insert here code to launch the default application
    self.close() # close this dialog
于 2013-10-03T20:15:47.950 回答