Почему подсказки QToolTip не отображаются в QActions в QMenu

Я делаю приложение с графическим интерфейсом, написанное с помощью PySide. Я поставил QMenu на QPushButton, добавил несколько QActions через QMenu.addAction. Чтобы объяснить пользователю эти действия, я добавил к ним QToolTip с QAction.setToolTip.

Когда я запускаю графический интерфейс, мой 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()

person Max Belli    schedule 12.02.2014    source источник


Ответы (4)


В Qt-5.1 или новее вы можете просто использовать QMenu.setToolTipsVisible, и элементы меню будут отображать всплывающие подсказки, как и ожидалось (см. QTBUG-13663):

    menu.setToolTipsVisible(True)

Однако для Qt-4.* и Qt-5.0 ситуация иная. Если действие добавлено на панель инструментов, его всплывающая подсказка будет показана; но если то же самое действие будет добавлено к QMenu, этого не будет, и нет встроенного API, чтобы изменить это. Есть несколько способов обойти это. Один из них – вместо этого использовать подсказки о статусе, которые будут показывать информация о пунктах меню в строке состояния. Другой способ заключается в самостоятельной реализации функциональности всплывающей подсказки пункта меню с помощью 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))
person ekhumoro    schedule 12.02.2014
comment
Спасибо, возможно, это не тот ответ, который я искал ;) - но он, безусловно, помог мне в пути! Я опубликую свое решение ниже - person Max Belli; 13.02.2014
comment
Следующий ответ (с использованием setToolTipsVisible в QMenu) на самом деле является правильным ответом для Qt 5.1+. - person Wingware; 02.10.2017
comment
@Вингваре. Первоначальный вопрос был о pyside и, следовательно, только о qt4. Однако теперь я обновил свой ответ, чтобы охватить как qt4, так и qt5. - person ekhumoro; 02.10.2017
comment
setToolTipsVisible не помогает на Mac. Возможно, собственные меню Mac не поддерживают это? - person Christopher Barber; 19.03.2021

На самом деле вам не нужно делать какие-либо обходные пути для отображения всплывающей подсказки, начиная с Qt 5.1, вы можете использовать свойство QMenu toolTipsVisible, для которого по умолчанию установлено значение false.

См. связанное с Qt предложение.

person CharlesB    schedule 24.11.2016
comment
Это действительно работает и должно быть принятым решением, вам нужно будет убедиться, что это свойство проверено для каждого меню и подменю, которые есть в вашем приложении, иначе всплывающие подсказки не будут отображаться для этих меню. - person ejectamenta; 20.01.2017

С помощью эхуморо я на пути к этому решению. Это, вероятно, не самая красивая вещь, и приведенный ниже код позиционирует меню и подсказки инструментов несколько в сторону, но в моей реальной программе это выглядит довольно аккуратно.

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 должна быть глобальной, поскольку лямбда-оператор не распознал ее, когда она была у меня в классе (self.show_toolTip). Я все еще открыт для предложений, если у кого-то есть предложение.

person Max Belli    schedule 13.02.2014
comment
Не уверен, что вы все еще заинтересованы, но я добавил более простое решение к своему ответу. - person ekhumoro; 14.02.2014

Вместо немедленного отображения всплывающей подсказки можно просто обновить всплывающую подсказку родителя (меню) при наведении курсора и дождаться отображения всплывающей подсказки! Следовательно:

    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())
person Leon Kos    schedule 17.11.2016