0

I have a custom QAbstractItemModel used to display information in a QTreeWidget. However, individual indices are drawn using a QStyledItemDelegate. One item that is drawn using the delegate is a pixmap. When the user hovers the mouse over the pixmap (either help event style or hover enter style is fine) I need to do something, what it is isn't important.

So my question is, how can I know when the mouse has hovered over a specific item inside a QTreeWidget, when that item is drawn using a delegate?

In other situations, I could just subclass QLabel, set the pixmap on it, and then do whatever I need in the event() function, but in this case there is no object behind the pixmap, it is just painted onto the screen, so it doesn't actually receive events. Is it possible to use the delegate to paint an actual widget where I want it to so that widget can receive events, or do I have to work around this some other way?

Cory Klein
  • 51,188
  • 43
  • 183
  • 243

2 Answers2

0

There is no Qt built-in solution to this problem. The problem can be solved, however, by saving the geometry of the individual items that are painted using the delegate as they are painted. The paint() function, however, has a const modifier so the data structure you use to save the geometry must be mutable. In this case, I don't think this constitutes a breach of the principles of OOP, but is rather a prime example of why the mutable keyword exists and when it should be used.

You then need to subclass QTreeWidget so you can re-implement the mouseMoveEvent() function as webclectic said. Inside that function you can compare the position of the mouse to the geometry of the item that you painted earlier. If the mouse is inside the item, then it is being hovered.

Cory Klein
  • 51,188
  • 43
  • 183
  • 243
0

You could subclass QTreeWidget and reimplement the mouseMoveEvent. In the event you can use the itemAt function in order to check if a valid item is at the mouse position and then do what you want.

void MyTreeWidget::mouseMoveEvent(QMouseEvent * event)
{
    QTreeWidget::mouseMoveEvent(event);
    QTreeWidgetItem* treeItem = itemAt(event->pos());
    if (treeItem != NULL)
       doSomething(treeItem); 
}

You could avoid subclassing QTreeWidget and implement it in the parent widget/main window. Notice however that the itemAt function expects coordinates in the widget's viewport so you should transform the coordinates to tree widget's coordinates. IMHO it is more elegant to subclass it and just implement the mouseMoveEvent function.

EDIT

If you need to detect the position of an icon within the widget item, it is a bit more advanced but you can check my answer to an older question for more details:

Position of icon in QTreeWidgetItem

Community
  • 1
  • 1
pnezis
  • 12,023
  • 2
  • 38
  • 38
  • The problem is not finding the QTreeWidgetItem, it is knowing whether the mouse is hovered over a specific item within the QTreeWidgetItem that I used the QStyledItemDelegate to paint. Imagine an icon that is to the right of the text of the QTreeWidgetItem. It's always in a different place because the length of the text is different. Or maybe it's in a randomized position completely. – Cory Klein Mar 23 '12 at 19:03