Как показать изображение всплывающей подсказки при наведении на кнопку pyqt5 - PullRequest
1 голос
/ 04 марта 2020

Я хочу показать изображение при наведении курсора на кнопку.

Но ссылка на всплывающую подсказку pyqt5 содержит только текст.

Как я могу это сделать? Я хочу сделать динамически, как для элемента l oop, как показано ниже

Мне нужно заполнить # код

def createButtons(self):
    for d_name in dic:
        btn = QPushButton(d_name, self)
        btn.clicked.connect(lambda state, x=d_name: self.btn_clicked(x))
        # btn.addTooltipImage(d_name)
        self.button_map[btn.text()] = btn

Ответы [ 2 ]

1 голос
/ 04 марта 2020

Всплывающая подсказка Qt поддерживает форматирование расширенного текста (только базовое c подмножество HTML), поэтому доступен тег <img>:

self.button.setToolTip('<img src="icon.svg">')

Помните, что если вы используете локальный путь к файлу, он должен быть абсолютным или относительным к пути файла, который его загружает.

Альтернативой является использование системы ресурсов Qt : вы можете создать файл ресурсов в Designer, затем создайте его, используя pyrcc myresource.qrc -o myresource.py, импортируйте его с import myresource и загрузите изображения, используя путь префикса двоеточия:

self.button.setToolTip('<img src=":/images/icon.svg">')

Анимированные подсказки (GIF)

Подсказки Как и любой другой виджет, основанный на QTextDocument , анимация не поддерживается. Единственное решение - создать собственный виджет, который ведет себя как всплывающая подсказка.

Для этого наиболее логичным подходом является создание подкласса QLabel, который поддерживает класс QMov ie. это обеспечивает поддержку анимированных изображений.

Обратите внимание, что это нелегко: хотя всплывающие подсказки могут показаться очень простыми объектами, их поведение следует многим аспектам, которые пользователь считает само собой разумеющимся. Чтобы имитировать c такое поведение, подкласс должен быть тщательно подобран таким же образом.

class ToolTipAnimation(QtWidgets.QLabel):
    def __init__(self, parent, file, width=None, height=None):
        super().__init__(parent, flags=QtCore.Qt.ToolTip)
        self.setMouseTracking(True)

        # image loading doesn't happen immediately, as it could require some time;
        # we store the information for later use
        self._file = file
        self._width = width
        self._height = height
        self._shown = False

        # a timer that prevents the enterEvent to hide the tip immediately
        self.showTimer = QtCore.QTimer(interval=100, singleShot=True)

        # install an event filter for the application, so that we can be notified
        # whenever the user performs any action
        QtWidgets.QApplication.instance().installEventFilter(self)

    def load(self):
        movie = QtGui.QMovie(self._file)
        if self._width and not self._height:
            self._height = self._width
        if self._width and self._height:
            size = QtCore.QSize(self._width, self._height)
            movie.setScaledSize(size)
        else:
            size = QtCore.QSize()
            for f in range(movie.frameCount()):
                movie.jumpToFrame(f)
                size = size.expandedTo(movie.currentImage().size())
        self.setFixedSize(size)
        self.setMovie(movie)
        self._shown = True

    def show(self, pos=None):
        if not self._shown:
            self.load()
        if pos is None:
            pos = QtGui.QCursor.pos()
        # ensure that the tooltip is always shown within the screen geometry
        for screen in QtWidgets.QApplication.screens():
            if pos in screen.availableGeometry():
                screen = screen.availableGeometry()
                # add an offset so that the mouse cursor doesn't hide the tip
                pos += QtCore.QPoint(2, 16)
                if pos.x() < screen.x():
                    pos.setX(screen.x())
                elif pos.x() + self.width() > screen.right():
                    pos.setX(screen.right() - self.width())
                if pos.y() < screen.y():
                    pos.setY(screen.y())
                elif pos.y() + self.height() > screen.bottom():
                    pos.setY(screen.bottom() - self.height())
                break

        self.move(pos)
        super().show()
        self.movie().start()

    def maybeHide(self):
        # if for some reason the tooltip is shown where the mouse is, we should
        # not hide it if it's still within the parent's rectangle
        if self.parent() is not None:
            parentPos = self.parent().mapToGlobal(QtCore.QPoint())
            rect = QtCore.QRect(parentPos, self.parent().size())
            if QtGui.QCursor.pos() in rect:
                return
        self.hide()

    def eventFilter(self, source, event):
        # hide the tip for any user interaction
        if event.type() in (QtCore.QEvent.KeyPress, QtCore.QEvent.KeyRelease, 
            QtCore.QEvent.WindowActivate, QtCore.QEvent.WindowDeactivate, 
            QtCore.QEvent.FocusIn, QtCore.QEvent.FocusOut, 
            QtCore.QEvent.Leave, QtCore.QEvent.Close, 
            QtCore.QEvent.MouseButtonPress, QtCore.QEvent.MouseButtonRelease, 
            QtCore.QEvent.MouseButtonDblClick, QtCore.QEvent.Wheel):
                self.hide()
        return False

    def mouseMoveEvent(self, event):
        QtCore.QTimer.singleShot(100, self.hide)

    def enterEvent(self, event):
        # hide the tooltip when mouse enters, but not immediately, otherwise it
        # will be shown right after from the parent widget
        if not self.showTimer.isActive():
            QtCore.QTimer.singleShot(100, self.hide)

    def showEvent(self, event):
        self.showTimer.start()

    def hideEvent(self, event):
        self.movie().stop()


class ButtonIcon(QtWidgets.QPushButton):
    toolTipAnimation = None
    formats = tuple(str(fmt, 'utf8') for fmt in QtGui.QMovie.supportedFormats())

    def setToolTipImage(self, image, width=None, height=None):
        if not image or self.toolTipAnimation:
            self.toolTipAnimation.hide()
            self.toolTipAnimation.deleteLater()
            self.toolTipAnimation = None
            self.setToolTip('')
            if not image:
                return
        if image.endswith(self.formats):
            self.toolTipAnimation = ToolTipAnimation(self, image, width, height)
        else:
            if width and not height:
                height = width
            if width and height:
                self.setToolTip(
                    '<img src="{}" width="{}" height="{}">'.format(
                        image, width, height))
            else:
                self.setToolTip('<img src="{}">'.format(image))

    def event(self, event):
        if (event.type() == QtCore.QEvent.ToolTip and self.toolTipAnimation and 
            not self.toolTipAnimation.isVisible()):
                self.toolTipAnimation.show(event.globalPos())
                return True
        elif event.type() == QtCore.QEvent.Leave and self.toolTipAnimation:
            self.toolTipAnimation.maybeHide()
        return super().event(event)


class Window(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        layout = QtWidgets.QHBoxLayout(self)
        buttonFixed = ButtonIcon('fixed image')
        buttonFixed.setToolTipImage('icon.svg')
        layout.addWidget(buttonFixed)
        buttonAnimated = ButtonIcon('animated gif')
        # the size can be set explicitly (if height is not provided, it will
        # be the same as the width)
        buttonAnimated.setToolTipImage('animated.gif', 200)
        layout.addWidget(buttonAnimated)
0 голосов
/ 04 марта 2020

PySide: добавление изображений во всплывающие подсказки

Это решение применимо к моему вопросу

btn.setToolTip('<br><img src="%s">' % (iconpath)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...