PDA

View Full Version : qmouseEvent handling



nass
9th October 2006, 11:31
hello everyone, i am trying to make a widget that will receive
mousePressEvent(QMouseEvent *e) for a widget of mine.
the thing is i have a QTextEdit that occupies most of the screen and
thus mouseEvents do not propagate to the widget which is my receiver
of choice for these events...
i read about QMouseEvent::ignore() but i am not sure this is what i
want... i basically want to make the textEdit (and any other objects
like buttons ill add later) 'transparent' so mouseEvents are directly
interpreted by the QWidget class.. ie the main window.
thank you
nass

high_flyer
9th October 2006, 11:51
Use evnt filter for that: http://doc.trolltech.com/3.3/qobject.html#installEventFilter

nass
9th October 2006, 13:00
im still abit fuzzy about its use..
the thing is in QtDesigner i am not given the option to add code for another class (the QObject needed for handling events here)... so im not sure where to declare it since if i do that directly in .ui/myForm.h it will be deleted on the next make clean..

but even besides that
where am i supposed to run the installEventFilter() function? in init? in order to connect the mouseEvents received on the textEdit, to the mouseEvents handler of myForm...?
nass

nass
9th October 2006, 13:33
hm i started making some sense.. but it doesn't work properly.
here is my .ui.h code:


void alarmScreen::init()
{
textScreen->installEventFilter( this );
}

void alarmScreen::closeButton_clicked()
{
//delete the alarm codes
accept();
}


void alarmScreen::upButton_clicked()
{
textScreen->scrollBy(0,-60);
}


void alarmScreen::downButton_clicked()
{
textScreen->scrollBy(0,60);
}


void alarmScreen::mousePressEvent( QMouseEvent *e )
{
printf("%d,%d\n",e->x(),e->y());
}


bool alarmScreen::eventFilter( QObject *obj, QEvent *ev )
{
//printf("got in\n");
QMouseEvent *e=(QMouseEvent *)ev;
if ( obj == textScreen )
{
printf("its the textEdit\n");
if ( e->type() == QEvent::MouseButtonPress )
{
printf("ad%d,%d\n",e->x(),e->y());
return TRUE;
}
}
else
{
printf("af: %d,%d\n",e->x(),e->y());
// pass the event on to the parent class
//return QMainWindow::eventFilter( obj, ev );
}
}

basically my form (alarmScreen) is a QWidget (640x320) and on top of it sits a QFrame of the same dimensions then on the frame sit a QTextEdit (in read only mode) and 3 buttons (a closeBt, a scrollUp and a scrollDown). it basically a trivial log viewer but i did not use the standard scrollbars of the QTextEdit because i need bigger buttons.
anyhow then i thought since it is so trivial i can delete the 2 scroll buttons and use the whole widget area for doing the scrolling (half the widget for scroll up and the other half for scroll down - forget the close button for a while).

what i did manage with the above code .. is that when i 'cross' the border of the QTextEdit alarmScreen::eventFilter is run and the printf() statement is executed... but of course
if ( e->type() == QEvent::MouseButtonPress fails since i have not clickd any button

what i had initially done was to implement the
void alarmScreen::mousePressEvent( QMouseEvent *e ) function
but that only works when i click on the frame... not when i click somewhere insie the QTextEdit...

any ideas or pointers?
thank you for your help
nass

gfunk
9th October 2006, 20:42
what i did manage with the above code .. is that when i 'cross' the border of the QTextEdit alarmScreen::eventFilter is run and the printf() statement is executed... but of course
if ( e->type() == QEvent::MouseButtonPress fails since i have not clickd any button


So does it work when you click inside the textScreen? If so, then maybe you can just re-post this textScreen event to your widget object, so that your ::mousePressEvent will be called?



QApplication::postEvent(alarmScreen, ev);

?

nass
9th October 2006, 20:50
nope it doesn't.
it only works when the mouse pointer 'flies' over the edges of the textEdit box... as if it only works when it flies over the frame of the textEdit..

but no the important thing is when i click on the textEdit the function eventFilter is not called...

nass

high_flyer
10th October 2006, 09:18
try this:


bool alarmScreen::eventFilter( QObject *obj, QEvent *ev )
{
//printf("got in\n");
QMouseEvent *e=(QMouseEvent *)ev;
if ( obj == textScreen->viewPort() )
{
printf("its the textEdit\n");
if ( e->type() == QEvent::MouseButtonPress )
{
printf("ad%d,%d\n",e->x(),e->y());
return TRUE;
}
}
else
{
printf("af: %d,%d\n",e->x(),e->y());
// pass the event on to the parent class
//return QMainWindow::eventFilter( obj, ev );
}

}

nass
10th October 2006, 11:18
i did that but now i can't even get to start the form... the eventFilter is run endlessly and sends the event directly to the parent:


bool alarmScreen::eventFilter( QObject *obj, QEvent *ev )
{
//printf("got in\n");
QMouseEvent *e=(QMouseEvent *)ev;
if ( obj == textScreen->viewport() )
{
printf("its the textEdit\n");
if ( e->type() == QEvent::MouseButtonRelease )
{
printf("ad %d,%d\n",e->x(),e->y());
return TRUE;
}
else
{
return FALSE;
}
}
else
if ( obj == this )
{
if ( e->type() == QEvent::MouseButtonRelease )
{
printf("af %d,%d\n",e->x(),e->y());
return TRUE;
}
else
{
return FALSE;
}
}
else
{
printf("sending event to parent");
return alarmScreen::eventFilter( obj, ev );
}
}

it's very weird behaviour.. because when the mouse pointer flies over QTextEdits's frame border the eventFilter procedure is called and even when i click on the QTextEdits's frame border the right branch is called.. also when i click on the frame that lies (and covers) all of QWidget (alarmScreen) works properly..

but, IN the white space of the QTextEdit (the writing space) it seems it is dead.. or that something else interecepts the mouse events before alarmScreen::eventFilter() can do so...
thank you for your attempts to help
nass

high_flyer
10th October 2006, 13:50
the eventFilter is run endlessly
Thats is beacouse you made a recursive call:


return alarmScreen::eventFilter( obj, ev );

There is no need for:


else
if ( obj == this )
{
if ( e->type() == QEvent::MouseButtonRelease )
{
printf("af %d,%d\n",e->x(),e->y());
return TRUE;
}
else
{
return FALSE;
}
}
else
{
printf("sending event to parent");
return alarmScreen::eventFilter( obj, ev );
}

Since you have methods to deal the objects own events.
Use the event filter only to filter events of the observed object.

high_flyer
13th October 2006, 08:55
else
{
printf("sending event to parent");
return alarmScreen::eventFilter( obj, ev );
}
I think what you meant here is to call the alarmScreen's parent class, in case it has reimplemented the eventFilter, if this is the case you should change
return alarmScreen::eventFilter( obj, ev ); to
return <alarmScreenParent>::eventFilter( obj, ev );

Otherwise as I said, you have a recursive call here.