我正在尝试实现一个“打开”按钮,这样如果用户按下并按住,则会弹出一个供用户选择的应用程序菜单;但是一旦用户释放鼠标,菜单就会消失。如果用户在未选择菜单上的应用程序的情况下释放鼠标,则应使用默认应用程序打开该文件。我将此按钮实现为QToolButton
并按如下方式连接信号:
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
信号,做一些检查以确定菜单是否应该弹出。因此,我通过继承QPushButton
和QMenu
来改变我的方法来编写自定义工具按钮。请参阅下面答案中的代码。
感谢。
答案 0 :(得分: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)
答案 1 :(得分: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