how to make a completely general tooltip in Qt

Viewed 44

I need to show a very complex tooltip for a widget. This tooltip should contain several texts (some of the texts are bold) organized in a form or table and also contain a dynamically generated image (painter to pixmap with QPainter). I know that QToolTip::showText(pos, text) can accept a rich-text/HTML formatted text. But since the subset of HTML which Qt supports is very limited, this is not sufficient in my usecase.

Is there a way to display a completely general QWidget with layouts, child widgets etc. as a tooltip? I do not require this tooltip to enable any user interaction, so not buttons, checkboxes, text edits etc. Just images and formatted text labels in generic layouts (in other words - just read-only widgets).

I know that I can instantiate QWidget with Qt::ToolTip window flag. But this does not solve my problem at all, I would still need to implement timers for show-up or close-down of the tooltip, react to mouse-move events, keeping just a single instance, etc. I checked the source code of QToolTip and the code is really complex... I do not want to duplicate this complex code.

Note that I have created a feature request https://bugreports.qt.io/browse/QTBUG-106785 so that Qt can enable this out of the box.

So is there any simple workaround before (if ever) this gets imlemented?

1 Answers

I have actually found the answer to my question. The purpose of my question was to share my solution with others so that they can use it in their code. I find this to be a very useful hack. It seems to work fine on all 3 major platforms - Windows, macOS, Linux.

Steps:

  1. Instantiate a temporary widget on the stack, add some layouts or child widgets in it as is needed in your usecase.
  2. Render this widget (though it is not displayed on screen) to a QPixmap.
  3. Serialize this pixmap to in-memory PNG-formatted byte array.
  4. Wrap this byte array to an <img/> HTML element in QString.
  5. Display the HTML in QToolTip:showText() function.
// instantiate a generic tooltip widget
QWidget toolTipWidget;
toolTipWidget.setWindowFlags(Qt::ToolTip);
toolTipWidget.setAutoFillBackground(true);
toolTipWidget.setBackgroundRole(QPalette::Base);
... here add whatever content to the widget you want, any child widgets, layouts etc.

// render the widget to pixmap and delete the widget
QPixmap pixmap(toolTipWidget.sizeHint());
QPainter painter(&pixmap);
toolTipWidget.render(&painter);

// generate in-memory PNG from the pixmap and wrap it in <img/> element
QByteArray data;
QBuffer buffer(&data);
pixmap.save(&buffer, "PNG");
QString html = QStringLiteral("<img src='data:image/png;base64, %1'/>").arg(QString::fromLatin1(data.toBase64()));

// and finally show in QToolTip
QToolTip::showText(globalPos, html);
Related