PDA

View Full Version : Graphicsitem hover highlight



Lykurg
17th July 2009, 10:30
Hi, simple case:
custom QGraphicsTextItem inside a normal QGraphicsScene and I want to change the background when the mouse is over the item.
So: setAcceptHoverEvents(true) and the hoverEnterEvent() of the item is triggered. Fine, but unless I don't call update() explicit, the background color wont change. (paint with QStyle::State_MouseOver checking.)

And here's the problem. I thought, that the paint method is automatically called when hovering the item, so that you don't have to reimp hoverEnterEvent etc. If that's right, what option do I miss? (there is no mouse grabber item)

Thanks,

Lykurg

wysota
17th July 2009, 11:28
Hi, simple case:
custom QGraphicsTextItem inside a normal QGraphicsScene and I want to change the background when the mouse is over the item.
So: setAcceptHoverEvents(true) and the hoverEnterEvent() of the item is triggered. Fine, but unless I don't call update() explicit, the background color wont change. (paint with QStyle::State_MouseOver checking.)
Do you call the base class implementation of the events?


And here's the problem. I thought, that the paint method is automatically called when hovering the item, so that you don't have to reimp hoverEnterEvent etc. If that's right, what option do I miss? (there is no mouse grabber item)

That's right. If it doesn't work then probably your paint implementation is incorrect. Can we see it?

Lykurg
17th July 2009, 12:02
Do you call the base class implementation of the events?
No, but that was just a test if the item receives the event. In the normal class I don't want to reimp the hoverEnterEvent.

That's right. If it doesn't work then probably your paint implementation is incorrect. Can we see it?
The strange thing is, that the paint function is not called.
The content is:

class EditSceneItem: public QGraphicsTextItem
{
Q_OBJECT

public:
EditSceneItem(QGraphicsItem *parent = 0);
virtual ~EditSceneItem();
void setWord(Word *word);

protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
Word *m_word;
};

//==========

EditSceneItem::EditSceneItem(QGraphicsItem *parent) :
QGraphicsTextItem(parent)
{
setAcceptHoverEvents(true);
setTextInteractionFlags(Qt::LinksAccessibleByMouse );
setZValue(50);
}

EditSceneItem::~EditSceneItem()
{
}

void EditSceneItem::setWord(Word *word)
{
m_word = word;
setPlainText(m_word->text());
}

void EditSceneItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
qWarning() << "paint!";
painter->save();
QRectF rect = option->rect;
QPen pen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
if (option->state.testFlag(QStyle::State_HasFocus) )
{
pen.setColor(QColor(140, 140, 140));
painter->setBrush(QColor(255, 255, 190));
}
else if (option->state.testFlag(QStyle::State_MouseOver))
{
pen.setColor(QColor(210, 210, 210));
painter->setBrush(QColor(248, 248, 248));
}
else
{// nonsense I know...
pen.setColor(Qt::transparent);
painter->setBrush(Qt::NoBrush);
}
painter->setPen(pen);
rect.translate(-0.5, -0.5);
painter->drawRoundedRect(rect, 5, 5);
painter->restore();

QStyleOptionGraphicsItem *o = const_cast<QStyleOptionGraphicsItem*> (option);
o->state &= ~QStyle::State_HasFocus;
QGraphicsTextItem::paint(painter, o, widget);
}



When hovering the item, "paint!" isn't shown up. adding
void EditSceneItem::hoverEnterEvent(QGraphicsSceneHover Event *event)
{
qWarning() << "hoverEnter";
QGraphicsTextItem::hoverEnterEvent(event);
}
prints me "hoverEnter" but no paint :confused:

Lykurg
18th July 2009, 21:23
Ok, it's wired, look following example:

#include <QtGui>

class myItem : public QGraphicsRectItem
{
public:
myItem(QGraphicsItem *parent = 0) : QGraphicsRectItem(parent)
{
setAcceptHoverEvents(true);
}

void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
{
if (option->state.testFlag(QStyle::State_MouseOver))
setBrush(QColor(0,230,230));
else
setBrush(QColor(230,230,230));
QGraphicsRectItem::paint(painter, option, widget);
}
};

class myItem2 : public QGraphicsTextItem
{
public:
myItem2(QGraphicsItem *parent = 0) : QGraphicsTextItem(parent)
{
setAcceptHoverEvents(true);
}

void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
{
painter->setBrush(QColor(230,230,230));
if (option->state.testFlag(QStyle::State_MouseOver))
painter->setBrush(QColor(0,230,230));
painter->drawRect(option->rect);
QGraphicsTextItem::paint(painter, option, widget);
}
};

class myItem3 : public QGraphicsSimpleTextItem
{
public:
myItem3(QGraphicsItem *parent = 0) : QGraphicsSimpleTextItem(parent)
{
setAcceptHoverEvents(true);
}

void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
{
painter->setBrush(QColor(230,230,230));
if (option->state.testFlag(QStyle::State_MouseOver))
painter->setBrush(QColor(0,230,230));
painter->drawRect(option->rect);
QGraphicsSimpleTextItem::paint(painter, option, widget);
}
};

int main(int argc, char **argv)
{
QApplication app(argc, argv);

QGraphicsScene scene;
myItem it;
it.setRect(0,0,30,30);
scene.addItem(&it);

myItem2 it2;
it2.setPlainText("test!");
scene.addItem(&it2);
it2.setPos(0,40);

myItem3 it3;
it3.setText("test2!");
scene.addItem(&it3);
it3.setPos(0,80);

QGraphicsView view(&scene);
view.show();

return app.exec();
}

myItem and myItem3 behaves like expected, myItem2 not. Even if you set various values for setTextInteractionFlags(). So I came to the conclusion it does not work for QGraphicsTextItem. The funny thing is that you can read in the docs to QGraphicsTextItem:

Note: QGraphicsTextItem accepts hover events by default. You can change this with setAcceptHoverEvents().
Hm, I guess that the above behavier is not intended. So it seems to be a bug special for QGraphicsTextItem. If nobody speaks against, I'll report it the next days...

wysota
19th July 2009, 22:05
Try redefining shape() of the item to boundingRect() and see what happens.

Lykurg
19th July 2009, 22:35
Hi, not quite sure if that is what you meant:

#include <QtGui>

class myItem2 : public QGraphicsTextItem
{
public:
myItem2(QGraphicsItem *parent = 0) : QGraphicsTextItem(parent)
{
setAcceptHoverEvents(true);
}

void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
{
painter->setBrush(QColor(230,230,230));
if (option->state.testFlag(QStyle::State_MouseOver))
painter->setBrush(QColor(0,230,230));
painter->drawRect(option->rect);
QGraphicsTextItem::paint(painter, option, widget);
}

QPainterPath shape() const
{
QPainterPath path;
path.addRect(boundingRect());
qWarning() << boundingRect();
return path;
}
};

int main(int argc, char **argv)
{
QApplication app(argc, argv);

QGraphicsScene scene;
myItem2 it2;
it2.setPlainText("test");
scene.addItem(&it2);
QGraphicsView view(&scene);
view.show();

return app.exec();
}


When hover the item shape is called with the correct bounding rect. But the background don't change.

wysota
19th July 2009, 23:01
But is paint() called or not?

Lykurg
19th July 2009, 23:07
But is paint() called or not?

no, it's not :(

wysota
20th July 2009, 00:25
I'd suggest using a debugger with a breakpoint on your path() implementation or on some of the hover events to see where the flow goes.

As a workaround I can suggest wrapping your text item into a rect item (with a parent-child relationship) and accepting hovers on the parent.

Lykurg
20th July 2009, 09:58
I'd suggest using a debugger with a breakpoint on your path() implementation or on some of the hover events to see where the flow goes.
I'll look on it closer that week.


As a workaround I can suggest wrapping your text item into a rect item (with a parent-child relationship) and accepting hovers on the parent.
Since the hover handlers get called, I simply added

protected:
void hoverEnterEvent(QGraphicsSceneHoverEvent *) {update();}
void hoverLeaveEvent(QGraphicsSceneHoverEvent *) {update();}
Thanks