I'm experiencing a strange problem in my application. I'm using a QGraphicsView along with a QGraphicsScene to display items. Some of the items have special tooltips which appear when the mouse hovers on top of them.

step1.png

The tooltips inherit QGraphicsTextItem in order to provide a border, margin, and custom background. Also, some of the items, which are children to the item with the current tooltip, also display a tooltip of their own when hovered.

step2.png

And now to the problem: When the second tooltip is removed (by moving the mouse out of the child item), the text of the first tooltip is cropped.

step3.png

This doesn't always happen but very often when the tooltips are displayed and then removed. Moreover, the same things sometimes happens even when there is no second tooltip over it. First I suspected this had something to do with the antialiasing, but deactivating it didn't remove the symptoms. I've provided a minimal working example below to isolate the problem.

Qt Code:
  1. #include <QApplication>
  2. #include <QGraphicsItem>
  3. #include <QGraphicsRectItem>
  4. #include <QGraphicsScene>
  5. #include <QGraphicsSceneHoverEvent>
  6. #include <QGraphicsTextItem>
  7. #include <QGraphicsView>
  8. #include <QMainWindow>
  9. #include <QPainter>
  10. #include <QPointF>
  11. #include <QRectF>
  12. #include <QSizeF>
  13. #include <QString>
  14. #include <QStyleOptionGraphicsItem>
  15.  
  16. class ToolTipItem : public QGraphicsTextItem {
  17. public:
  18. ToolTipItem(const QString& text)
  19. {
  20. setAcceptHoverEvents(true);
  21. }
  22.  
  23. virtual ~ToolTipItem(void) {}
  24.  
  25. virtual QRectF boundingRect(void) const {
  26. QRectF rect(QPointF(0, 0), getSize());
  27. qreal d = BORDER_WIDTH / 2;
  28. rect.adjust(-d, -d, d, d);
  29. return rect;
  30. }
  31.  
  32. virtual void paint(
  33. QPainter* painter,
  34. QWidget* widget)
  35. {
  36. // Draw surrounding box
  37. painter->setPen(QPen(BORDER_COLOR, BORDER_WIDTH));
  38. painter->setBrush(QBrush(BACKGROUND_COLOR));
  39. QRectF rect(QPointF(0, 0), getSize());
  40. painter->drawRect(rect);
  41.  
  42. // Draw text content
  43. painter->translate(QPointF(MARGIN, MARGIN));
  44. QGraphicsTextItem::paint(painter, option, widget);
  45. }
  46.  
  47. virtual QPainterPath shape(void) const {
  48. path.addRect(boundingRect());
  49. return path;
  50. }
  51.  
  52. QSizeF getSize(void) const {
  53. QRectF rect(QGraphicsTextItem::boundingRect());
  54. rect.adjust(0, 0, 2*MARGIN, 2*MARGIN);
  55. return rect.size();
  56. }
  57.  
  58. void placeNextTo(QGraphicsItem* item) {
  59. QPointF item_point_in_scene =
  60. item->mapToScene(item->boundingRect().topLeft());
  61. qreal x_pos = item_point_in_scene.x() - boundingRect().size().width()
  62. + 1.5 * BORDER_WIDTH;
  63. qreal y_pos = item_point_in_scene.y() + BORDER_WIDTH / 2;
  64. QPointF tooltip_point_in_scene(x_pos, y_pos);
  65. setPos(tooltip_point_in_scene);
  66. }
  67.  
  68. protected:
  69. static const QColor BACKGROUND_COLOR;
  70. static const qreal MARGIN;
  71. static const qreal BORDER_WIDTH;
  72. static const QColor BORDER_COLOR;
  73. };
  74.  
  75. const QColor ToolTipItem::BACKGROUND_COLOR(Qt::white);
  76. const qreal ToolTipItem::MARGIN = 5;
  77. const qreal ToolTipItem::BORDER_WIDTH = 1;
  78. const QColor ToolTipItem::BORDER_COLOR(Qt::black);
  79.  
  80. class MyItem : public QGraphicsRectItem {
  81. public:
  82. MyItem(qreal x, qreal y, qreal width, qreal height,
  83. QGraphicsItem* parent = 0)
  84. : QGraphicsRectItem(x, y, width, height, parent),
  85. tooltip_(NULL)
  86. {
  87. setAcceptHoverEvents(true);
  88. }
  89.  
  90. virtual ~MyItem(void) {}
  91.  
  92.  
  93. protected:
  94. virtual void hoverEnterEvent(QGraphicsSceneHoverEvent* event) {
  95. event->accept();
  96. if (!tooltip_) {
  97. tooltip_ = new ToolTipItem("bla bla bla\nfadsf asdf\nfdasdfas");
  98. tooltip_->placeNextTo(this);
  99. scene()->addItem(tooltip_);
  100. }
  101. tooltip_->show();
  102. }
  103.  
  104. virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event) {
  105. event->accept();
  106. if (tooltip_) tooltip_->hide();
  107. }
  108.  
  109. private:
  110. ToolTipItem* tooltip_;
  111. };
  112.  
  113.  
  114.  
  115. int main(int argc, char** argv) {
  116. QApplication app(argc, argv);
  117.  
  118. MyItem* item1 = new MyItem(0, 0, 50, 50);
  119. MyItem* item2 = new MyItem(20, 10, 10, 10, item1);
  120. MyItem* item3 = new MyItem(20, 20, 10, 10, item2);
  121. scene->addItem(item1);
  122.  
  123. QGraphicsView* view = new QGraphicsView(scene);
  124. view->setRenderHint(QPainter::Antialiasing);
  125. QMainWindow window;
  126. window.setCentralWidget(view);
  127. window.show();
  128.  
  129. return app.exec();
  130. }
To copy to clipboard, switch view to plain text mode