Displaying a tooltip when mouse hovers over part of Widget
-
I have a widget subclass that displays an image in part of its real-estate.
When the mouse hovers over the image I want to display a tooltip, but only if it is in that part of the widget that contains the image, so QWidget::setToolTip() isn't perfect for the job - though I can use that as a fall back solution.
I already have handlers in place for mousePressEvent, mouseMoveEvent, and mouseReleaseEvent.
I tried to find hoverEnterEvent and hoverLeaveEvent for QWidget, but AFAICT these don't exist.
What's the best way to handle this please?
-
So the trick is to capture the QEvent::ToolTip event in event() and invoke showText on the relevant rectangle? Is that right?
Here's what I did:
bool DSSImageView::event(QEvent* event) { if (QEvent::ToolTip == event->type()) { // // Create a rectangle representing the image area // QRect rect(m_origin.x(), m_origin.y(), (m_pixmap.width() * m_scale), (m_pixmap.height() * m_scale)); // // Get the tooltip text if any and if the mouse is over the image, show the tooltip // const QString tip = toolTip(); if (!tip.isEmpty()) { const QPoint mouseLocation(QCursor::pos()); QToolTip::showText(mouseLocation, tip, this, rect); } return true; } // Make sure the rest of events are handled return Inherited::event(event); }
but the tooltip was displayed regardless of where in the widget the mouse was (IOW, not just in rect { x = 0, y = 83, width = 500, height = 333 } almost as if I'd called the version of showText that didn't use rect).
So it would seem that there's a bug in QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect)
The following code does work:
bool DSSImageView::event(QEvent* event) { if (QEvent::ToolTip == event->type()) { // // If the mouse is over the image, but not over the toolbar, // get the tooltip text and if there is any, display it // const QPoint globalMouseLocation(QCursor::pos()); const QPointF mouseLocation(mapFromGlobal(globalMouseLocation)); if (mouseOverImage(mouseLocation) && !m_pToolBar->underMouse()) { const QString tip = toolTip(); if (!tip.isEmpty()) { QToolTip::showText(globalMouseLocation, tip, this); } } return true; } // Make sure the rest of events are handled return Inherited::event(event); }
-
@Perdrix You can specify where to show a tooltip: https://doc.qt.io/qt-5/qtooltip.html#showText
-
So the trick is to capture the QEvent::ToolTip event in event() and invoke showText on the relevant rectangle? Is that right?
Here's what I did:
bool DSSImageView::event(QEvent* event) { if (QEvent::ToolTip == event->type()) { // // Create a rectangle representing the image area // QRect rect(m_origin.x(), m_origin.y(), (m_pixmap.width() * m_scale), (m_pixmap.height() * m_scale)); // // Get the tooltip text if any and if the mouse is over the image, show the tooltip // const QString tip = toolTip(); if (!tip.isEmpty()) { const QPoint mouseLocation(QCursor::pos()); QToolTip::showText(mouseLocation, tip, this, rect); } return true; } // Make sure the rest of events are handled return Inherited::event(event); }
but the tooltip was displayed regardless of where in the widget the mouse was (IOW, not just in rect { x = 0, y = 83, width = 500, height = 333 } almost as if I'd called the version of showText that didn't use rect).
So it would seem that there's a bug in QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect)
The following code does work:
bool DSSImageView::event(QEvent* event) { if (QEvent::ToolTip == event->type()) { // // If the mouse is over the image, but not over the toolbar, // get the tooltip text and if there is any, display it // const QPoint globalMouseLocation(QCursor::pos()); const QPointF mouseLocation(mapFromGlobal(globalMouseLocation)); if (mouseOverImage(mouseLocation) && !m_pToolBar->underMouse()) { const QString tip = toolTip(); if (!tip.isEmpty()) { QToolTip::showText(globalMouseLocation, tip, this); } } return true; } // Make sure the rest of events are handled return Inherited::event(event); }