PDA

View Full Version : Using custom events.



hickscorp
16th June 2010, 12:38
Hello,

i'm having this in my code:
class AWBObject : public QGraphicsItem {
public:
// Event types.
static const QEvent::Type HoverEnter = static_cast<QEvent::Type>(QEvent::User+1);
static const QEvent::Type HoverLeave = static_cast<QEvent::Type>(QEvent::User+2);
// Base event class.
class Event : public QEvent {
public:
Event (QEvent::Type type) : QEvent(type) {};
AWBObject *object;
};
// Hover enter event.
class HoverEnterEvent : public AWBObject::Event {
public:
HoverEnterEvent () : Event(HoverEnter) {};
};
// Hover leave event.
class HoverLeaveEvent : public AWBObject::Event {
public:
HoverLeaveEvent () : Event(HoverLeave) {};
};
[...]
};

Then on a QGraphicItem "hoverEnterEvent" and "hoverLeaveEvent" i'm doing something like this:
if (scene()) {
HoverEnterEvent *toSend = new HoverEnterEvent();
toSend->object = this;
QCoreApplication::sendEvent((QObject*)scene(), toSend);
}
QGraphicsItem::hoverEnterEvent(evt);

Then in my scene subclass:
void WBScene::customEvent (QEvent *evt) {
switch (evt->type()) {
case AWBObject::HoverEnter:
_highlight = ((AWBObject::Event*)evt)->object;
if (_highlight) _highlight->setHighlighted(true);
return;
case AWBObject::HoverLeave:
_highlight = ((AWBObject::Event*)evt)->object;
if (_highlight) _highlight->setHighlighted(false);
return;
default:
return QGraphicsScene::customEvent(evt);
}
}

Saddly, the event isn't received by the scene. If i post a regular event (e.g. Just propagage the QGraphicsSceneHoverEvent), it's received by the scene in the event() method. i've tried both event() and customEvent() in the scene subclass, in either case the custom event is received.

Note that i'm doing this after i instanciate my QApplication (And before execing the loop):
QEvent::registerEventType(AWBObject::HoverEnter);
QEvent::registerEventType(AWBObject::HoverLeave);

high_flyer
16th June 2010, 13:01
Did you register the custom event?
QEvent::registerEventType ( )

hickscorp
16th June 2010, 13:26
Hello High Flyer, and thank you for your time.

Yes, i have registered my types (See the end of my post, last code block...).

Pierre.

agathiyaa
16th June 2010, 14:03
Hi ,

Will this help ?



HoverEnterEvent toSend;
toSend.object = this;
QCoreApplication::sendEvent((QObject*)scene(),&toSend);


If you call postEvent(), you must create the event object using new and Qt will automatically delete it after it is processed. If you call sendEvent(), you must create the event on the stack.

hickscorp
16th June 2010, 16:25
Really, it doesn't change anything. Thanks anyway. Anyone, UP?

agathiyaa
16th June 2010, 20:04
Hi,
It works perfectly for me. The Problem may be in your Scene's MouseMoveEvent. Please make sure QGraphicsScene::mouseMoveEvent(...) is called in your derrived Scene Class.



void QLMyItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event )
{
if (scene()) {
MyEvent e(QLMyItem::HoverLeave);
e.object = (void*)this;
QCoreApplication::sendEvent((QObject*)scene(), &e);
}
QGraphicsItem::hoverLeaveEvent(event);
}

wysota
17th June 2010, 02:45
Did you ask the view to deliver hover events to your item in the first place?

hickscorp
17th June 2010, 09:45
Hello, and thank you for your time.

@Agathiyaa: My scene overrides these functions (mouseMoveEvent, Press, Release, DragEnter, DragLeave, Drop...). The problem clearly doesn't come from there, since i'm able to catch NON-CUSTOM events from my scene if my QGraphicsItem re-posts / re-sends it.

@Wysota: My view delivers hoverring events. Again: my items receive the hover events. i can propagate them to the scene. Only, if i try to propagate my own events instead, it just never get catched by my scene.

Thanks,
Pierre.

hickscorp
17th June 2010, 09:52
Wow. i just tried something and it works. Actually i'm trying to post a HoverEnterEvent and a HoverLeaveEvent (Both derived from my Event class, and both calling the Event constructor with a different type). This didn't work. Now i have just tried to directly construct an Event and send it.

Guess what... it works, and get catched as expected.

May be a bug? Maybe Qt accepts subclasses of QEvent, but not sub-subclasses?

wysota
17th June 2010, 10:11
May be a bug?
Nope, an optimization.

hickscorp
17th June 2010, 10:22
An Optimization? i'm not sure i understand... Now i've pointed it out, you know it's an optimization? :D Why not telling it in the doc then?... i really don't think it's an optimisation (When registering a new event type, it's based on it's type #ID, not it's class... If internally Qt does a type check based on the class, it makes no sense... i don't even think it's possible, since QEvent is not a subclass of QObject, and since my subclasses don't Q_OBJECT, it's not possible to get the superclass at runtime.

Explain me, i really hate to get vague guesses :)

Pierre.

wysota
17th June 2010, 10:32
An Optimization? i'm not sure i understand...
There is no point in tracking mouse position on the items (which requires coordinate transformations and collision detection) if you know the mouse is not in any of the views that hold the items. There is no point in tracking the mouse to detect hover events if you know the mouse is not over the item, etc. I'd assume it's exactly the same for widgets, although it might be a bit different as there is no scene equivalent for widgets so you'd post the event directly to the widget and this will probably just work (although Qt will not try to detect hover events by itself).


Now i've pointed it out, you know it's an optimization? :D
It's just logical to assume so. Qt is open source, you can easily verify my assumption by reading its source code.


Why not telling it in the doc then?...
If every detail was covered in the docs and every possible abuse of Qt was warned about in the docs, then the docs would have several gigabytes of volume and there would still be creative people who would invent new ways of abusing Qt.

high_flyer
17th June 2010, 11:31
Now i have just tried to directly construct an Event and send it.

Guess what... it works, and get catched as expected.

Isnt it what hickscorp suggested to you in his post above? specifically the quaote from the doc?

hickscorp
17th June 2010, 11:35
There is no point in tracking mouse position on the items (which requires coordinate transformations and collision detection) if you know the mouse is not in any of the views that hold the items. There is no point in tracking the mouse to detect hover events if you know the mouse is not over the item, etc. I'd assume it's exactly the same for widgets, although it might be a bit different as there is no scene equivalent for widgets so you'd post the event directly to the widget and this will probably just work (although Qt will not try to detect hover events by itself).
It's just logical to assume so. Qt is open source, you can easily verify my assumption by reading its source code.
If every detail was covered in the docs and every possible abuse of Qt was warned about in the docs, then the docs would have several gigabytes of volume and there would still be creative people who would invent new ways of abusing Qt.
i'm not sure you see the problem.... The mouse is tracked, whatever if there is a point or not (QGraphicsItem has the hovering methods virtual, which allows subclassing + overriding). it's not a mouse tracking related problem. it's an custom event propagation problem. i could be trying to post ANY other kind of event (Even NOT hover-related), as long as they are custom, derived from a class itself derived from QEvent, it won't work.

Try it yourself. Make a class A, derived from QEvent. Make a class B, derived from A. Register a custome event type assigned to either A or B. Post a B. (You'll never receive it in your target, whatever you're using post or send). Try this outside any QGraphics context, again: i'm really not talking about any hover / mouse / move thingy stuff.

@high_flier: Sorry, i don't understand your answer. Are you misstaking me with me? :D You're saying i'm suggesting myself something? XD

wysota
17th June 2010, 11:44
Only GUI-related events are propagated. Custom events are not GUI related.

high_flyer
17th June 2010, 11:50
@high_flier: Sorry, i don't understand your answer. Are you misstaking me with me? :D You're saying i'm suggesting myself something? XD

I meant agathiyaa.

agathiyaa
17th June 2010, 20:30
Hi...

I have found the exact problem in your code.


Qt ( C++) allows / accepts subclasses of QEvent, Also sub-subclasses / throughout the inheritance hierarchy

It seems "HoverEnter" & "HoverLeave" is defined or used somewhere else. If you try different name or

class HoverEnterEvent : public AWBObject::Event {
public:
HoverEnterEvent () : Event(AWBObject::HoverEnter) {};
};
it should work for you as is.(Note: AWBObject::HoverEnter)

Please give a try and let us know. It worked for me.