PDA

View Full Version : leaveEvent on transparent area issue



nooky59
2nd January 2008, 13:35
Happy new year everybody !

I have a tricky problem with Qt (last release 4.3.3).

I have a widget with transparency (I use the ARGB widget trick from the wiki) and as soon as I am on a transparent area, a leaveEvent is triggered.

The problem is it is not really leaved as I am still on the widget but in a transparent area.

I would like to be able to check the mouse location in transparent areas and only consider it is leaved if the mouse location is at some location on the transparent area.

Is it possible ? I've tried with grabMouse but it seems I dont' have mouseMouveEvent in transparent areas (sure setMouseTracking is set to true ;o)).

Many thanks in advance for your answers.

maverick_pol
2nd January 2008, 14:13
Hi,

Does it work if you use Qt::transparent as the color of your widget?

Maverick

nooky59
2nd January 2008, 14:25
Hi,

Does it work if you use Qt::transparent as the color of your widget?

Maverick

I don't think so cause I use Qt::transparent to fill the QPainter then applying some PNG pixmaps with half-transparency.

The problem is not related to half-transparency but clearly to transparency cause I lost the events in full transparency areas.

Sure if I don't fill my widget with transparency, the mouse tracking is still enabled.

I really need to make a distinction between a fake leaveEvent and a true leaveEvent (when the mouse is outside of the widget full rect, the main window in fact).

nooky59
2nd January 2008, 16:30
I have digged a little more on the forum (although I have previously done it before posting my thread) and I've found that :


The static method QCursor::pos() could be called to obtain the hotspot of the cursor in screen coordinates. I can then compare ths QPoint to my widget and take a decision.

I've still one design issue about that so I need avdices of experts ;o) I've made the test in the leaveEvent but it's one shot (as for me I'm still in the transparent area of the widget).

So I must periodically check the mouse to see where it is. What is the best way to do this (thread, timer, other construct) ?

Moreover I don't think I must stay with setMouseTracking(true) on my widget as it can't track it on the transparent areas. Perhaps it would be better to have an entity (as I have asked just above) specialized in the mouse tracking ?

Furthermore, my widget will have an autohide functionnality and it will reappear when the mouse stay enough time at the border of the screen so it will become fully transparent if auto-hidden so I must really track the mouse elsewhere than at this widget level.

Any expert advice is welcome ;o)

I have another idea that come in mind by reading the Qt doc but I don't know if it's a realistic option :

QDesktopWidget is a children of QWidget so perhaps it is possible to inherit from QDesktopWidget, set mouse tracking to true and implement the events in my child class of QDesktopWidget ?

high_flyer
2nd January 2008, 22:22
So I must periodically check the mouse to see where it is. What is the best way to do this (thread, timer, other construct) ?
When the mouse moves over any widget of your application, some widget gets that event.
If the transparent widget does not, then the one behind it probably does.
Try see if you could make an eventFilter (http://doc.trolltech.com/4.3/qobject.html#eventFilter) could be fitted in your widget hierarchy in a convenient way, this will eliminate the need for polling.
This actually looks to go well with the other points you made after this one.
Polling in such cases is not good since you risk missing events.

nooky59
3rd January 2008, 10:04
When the mouse moves over any widget of your application, some widget gets that event.
If the transparent widget does not, then the one behind it probably does.
Try see if you could make an eventFilter (http://doc.trolltech.com/4.3/qobject.html#eventFilter) could be fitted in your widget hierarchy in a convenient way, this will eliminate the need for polling.
This actually looks to go well with the other points you made after this one.
Polling in such cases is not good since you risk missing events.

I think there is a big problem with that approach as my problematic widget is the top-level widget.

I have perhaps one simple and stupid solution... Rather than filling the transparent areas of my widget with Qt::transparent, perhaps it would be better to fill it with QRgba(0, 0, 0, 1).

Do you think it's a good idea ? The difference between the pure desktop areas and the one overlapped by QRga(0, 0, 0, 1) must not be really noticeable and there is no need to do polling.

Any reason not to do that ?

high_flyer
3rd January 2008, 10:22
I think there is a big problem with that approach as my problematic widget is the top-level widget.
I don't know if this will work, but you can try see if you can use QDesktopWidget for taping to these event.
But my guess is that it will not work, since probably QDesktopWidget will be in global (not your application) scope.
But its worth a try.

nooky59
3rd January 2008, 10:37
I don't know if this will work, but you can try see if you can use QDesktopWidget for taping to these event.
But my guess is that it will not work, since probably QDesktopWidget will be in global (not your application) scope.
But its worth a try.

Yes, it was my idea cause QDesktopWidget inherits from QWidget so there is the mouse events.

But as it is written in the Qt doc : Instead of using QDesktopWidget directly, use QApplication::desktop(). I don't think I can inherits my own DesktopWidget from QDesktopWidget, reimplement events and then construct it in my code without calling QApplication::desktop()...

But perhaps by digging with events filter and tryin' to intercept the QDesktopWidget events...

But I think I will stick with QRgba(0, 0, 0, 1) as I don't notice a difference between the overlayed areas and the pure areas of the desktop.

high_flyer
3rd January 2008, 10:59
use QApplication::desktop()
That's what I meant.

nooky59
3rd January 2008, 13:21
Ok, Rgba(0,0,0, 1) or whatever color with an alpha value of 1 is definitively a bad idea ! :(

It could be noticed a little depending of the screen color and the viewing angle for a LCD screen.

Moreover, my co-worker who is the infographic artist told me that it could be far more noticeable on CRT screen with a particular contrast.

I will have to dig and I'll try with the QDesktopWidget

nooky59
8th January 2008, 13:22
Just for information, events filtering on the QDesktopWidget doesn't work so much :

In my constructor :



desktop = QApplication::desktop();
desktop->installEventFilter(this);
desktop->setMouseTracking(true);


And in the event :



bool MyWidget::eventFilter(QObject *target, QEvent *event)
{
int tmp = -1;
if(target == desktop)
{
tmp = event->type();

switch(tmp)
{
case 109: // Mouse tracking state change
case 74: // Should be Polished
case 75: // Is Polished
break;

default:
tmp = tmp;
break;
}
}

return false;
}


I've set a breakpoint on the tmp = tmp line in the default case.

I can only seen the third events from the switch / case (perhaps some others, I haven't tried everything but mouse moves and keypress didn't falled in the events filter.

But I've told you that QColor(0, 0, 0, 1) could be visible on a screen, even on an LCD depending of the way you look at it.

It seems that QColor(255, 255, 255, 1) is less visible, I can't see the semi-transparency, it appears really transparent.

The infographic artist told me that a 50% grey QColor(127, 127, 127, 1) is even more neutral.

Hope it could help. If someone has a CRT screen with a crazy contrast rate, just tell me if you see something on a single color desktop background ;o)