为什么QMenu中的QAction上不会出现QToolTips

13

我正在使用PySide编写GUI的应用程序。 我在QPushButton上设置了一个QMenu,通过QMenu.addAction添加了几个QActions。 为了进一步向用户解释这些操作,我使用了QAction.setToolTipQToolTip添加到这些操作中。

现在运行GUI时,我的QToolTip不会显示。 下面发布的示例复制了相同的问题,有任何想法吗?

提前感谢

import sys
from PySide import QtGui

class Example(QtGui.QPushButton):

    def __init__(self, parent = None):
        super(Example, self).__init__(parent)

        self.setText('TestMenu')
        self.setToolTip('This is a Test Button')

        menu = QtGui.QMenu(self)
        action_1 = menu.addAction('Action1')
        action_1.setToolTip('This is action 1')
        action_2 = menu.addAction('Action2')
        action_2.setToolTip('This is action 2')
        action_3 = menu.addAction('Action3')
        action_3.setToolTip('This is action 3')
        action_4 = menu.addAction('Action4')
        action_4.setToolTip('This is action 4')

        self.setMenu(menu)
        self.show()

def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()

    app.exec_()

if __name__ == '__main__':
    main()
4个回答

24
在Qt-5.1或更高版本中,您可以简单地使用QMenu.setToolTipsVisible,然后菜单项将按预期显示其工具提示(参见QTBUG-13663):
    menu.setToolTipsVisible(True)

然而,对于Qt-4.*和Qt-5.0,情况有所不同。如果将一个操作添加到工具栏,它的工具提示将会被显示;但是,如果将相同的操作添加到QMenu中,则不会显示,也没有内置的API来更改这一点。有几种方法可以解决这个问题。其中一种方法是使用status tips,它将在状态栏中显示菜单项信息。另一种方法是使用QMenu.hovered信号和QToolTip.showText自己实现菜单项工具提示功能:
        self.menu = QtGui.QMenu(self)
        ...
        self.menu.hovered.connect(self.handleMenuHovered)

    def handleMenuHovered(self, action):
        QtGui.QToolTip.showText(
            QtGui.QCursor.pos(), action.toolTip(),
            self.menu, self.menu.actionGeometry(action))

谢谢,可能不是我想要的答案 ;) - 但它确实帮助我入门了!我会在下面发布我的解决方案 - Max Belli
下一个答案(使用QMenu上的setToolTipsVisible)实际上是Qt 5.1+的正确答案。 - Wingware
@Wingware。原始问题是关于PySide的,因此仅涉及Qt4。但是,我现在已更新我的答案,来涵盖Qt4和Qt5。 - ekhumoro
setToolTipsVisible 在 Mac 上似乎没有帮助。也许 Mac 原生菜单不支持它? - Christopher Barber

9
实际上,您不需要进行任何变通来显示工具提示,因为自Qt 5.1以来,您可以使用QMenu的属性toolTipsVisible,默认设置为false
请参见相关的Qt建议

1
这真的有效,并应该被接受为解决方案,您必须确保对应用程序中的每个菜单和子菜单都检查了此属性,否则将无法显示工具提示。 - ejectamenta

2

在悬停时更新父级菜单的工具提示,并等待工具提示显示,而不是立即显示工具提示!因此:

    menu = QtGui.QMenu(self)
    action_1 = menu.addAction('Action1')
    action_1.setToolTip('This is action 1')
    ...
    menu.hovered.connect(self.handleMenuHovered)

def handleMenuHovered(self, action):
    action.parent().setToolTip(action.toolTip())

2

在ekhumoro的帮助下,我找到了这个解决方案。也许它并不是最美丽的东西,下面的代码将菜单和工具提示位置有些尴尬,但在我的实际程序中看起来相当整洁。

import sys
from PySide import QtGui, QtCore

class Example(QtGui.QPushButton):

    def __init__(self, parent = None):
        super(Example, self).__init__(parent)

        self.setText('TestMenu')
        self.setToolTip('This is a Test Button')

        menu = QtGui.QMenu(self)
        action_1 = menu.addAction('Action1')
        action_1.setToolTip('This is action 1')
        action_2 = menu.addAction('Action2')
        action_2.setToolTip('This is action 2')
        action_3 = menu.addAction('Action3')
        action_3.setToolTip('This is action 3')
        action_4 = menu.addAction('Action4')
        action_4.setToolTip('This is action 4')

        action_1.hovered.connect(lambda pos = [self], parent = action_1, index = 0: show_toolTip(pos, parent, index))
        action_2.hovered.connect(lambda pos = [self], parent = action_2, index = 1: show_toolTip(pos, parent, index))
        action_3.hovered.connect(lambda pos = [self], parent = action_3, index = 2: show_toolTip(pos, parent, index))
        action_4.hovered.connect(lambda pos = [self], parent = action_4, index = 3: show_toolTip(pos, parent, index))

        self.setMenu(menu)
        self.show()

def show_toolTip(pos, parent, index):
    '''
    **Parameters**
        pos:    list
            list of all parent widget up to the upmost

        parent: PySide.QtGui.QAction
            the parent QAction

        index:  int
            place within the QMenu, beginning with zero
    '''
    position_x = 0
    position_y = 0
    for widget in pos:
        position_x += widget.pos().x()
        position_y += widget.pos().y()

    point = QtCore.QPoint()
    point.setX(position_x)
    point.setY(position_y + index * 22) # set y Position of QToolTip

    QtGui.QToolTip.showText(point, parent.toolTip())

def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()

    app.exec_()

if __name__ == '__main__':
    main()

我必须说,我对此并不完全满意,主要是因为show_toolTip函数必须是全局的,因为当我将它放在类中时,lambda运算符无法识别它(self.show_toolTip)。如果有人有建议,我仍然乐意听取。


不确定你是否还有兴趣,但我已经在我的答案中添加了一个更简单的解决方案。 - ekhumoro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接