PDA

View Full Version : Problem in MouseMoveEvent



aamer4yu
1st November 2006, 07:46
I have a mainwindow inherited from QMainWindow, This contains a central widget which holds a scene and a view.

I have overloaded mouseMoveEvent() for both central widget i am using and for mainwindow too.
The problem is , I am not getting events in the overloaded mouseMoveEvent() in MainWindow class. How do I get the events in MainWindow's mouseMoveEvent function too ?? :confused:

I want to display the cursor position in the view in the status bar of the main window...ne suggestions ??

jpn
1st November 2006, 07:59
Read notes about mouse tracking (http://doc.trolltech.com/4.2/qwidget.html#mouseTracking-prop) in QWidget::mouseMoveEvent() docs.

aamer4yu
1st November 2006, 09:13
I had read that before...
and have set mouse tracking to true in the main window...

i do get messages for that... but when i am at the boundary of the main window..
when i am inside the view area, i dont get events in the main window...

in other words, how do i set that i receive mouse evenst in the main window first and then passed on to the scene or view area ??

jpn
1st November 2006, 09:53
Ahh ok. It's the central widget which receives mouse move events when the mouse is over it. You can try to ignore the event (http://doc.trolltech.com/4.2/qevent.html#ignore) so that it might get propagated to it's parent (which would be the main window). I'm not sure if it works as desired. Alternatively you can install an event filter (http://doc.trolltech.com/4.2/eventsandfilters.html) on the central widget or deliver the position information from the central widget to the main window for example by using signals and slots..

aamer4yu
2nd November 2006, 04:48
Well.. I tried a bit with catching mouse movements in the main widget, but still not successfull...

here is the class I am using for main widget..


class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent=0);
~MainWidget();

private:
//void setupMatrix();
void populateScene();

View *view;

QGraphicsScene *scene;
QList<CMacro*> macroList;

protected:
void mouseMoveEvent ( QMouseEvent * event );
void paintEvent(QPaintEvent *event);
};

Here I have a scene and view.... and overloaded mouseMoveEvent function. Still when i move cursor across the view area, I dont get any events in this MainWidget::mouseMoveEvent () :(

Do i need to make my own class for scene and overload the mousevent function in that class ??:confused:

jpn
2nd November 2006, 07:01
You can install an event filter on the view.

aamer4yu
8th November 2006, 06:14
well.. quite late to solve this problem :crying: i was away fr some days...

back to the problem... i tried deriving classess and handling events through mousemoveevents but in vain.
I also installed eventfilter in mainwindow(derived frm QMainWindow) , but i dont receive mousemoveevents in that :-(

Next I tried sending event from view to parent (CViewFrame derived from QFrame). This worked, and I was able to track cursor position in Mainwindow's status bar. But problem occured in moving graphic items in the view.

Is there not any simple way to know the cursor position in the QMainWindow ??:confused:
Even if i install event filter, i dont receive QEvent::MouseMove or QEvent::HoverEnter. What event is passed on to QMainWindow when mouse moves ??? and how do i capture it in event filter ??

aamer4yu
8th November 2006, 06:52
aaahhh... shud have waited a while to post above..

finally got the solution though not much efficient..

i traced the cursor in paintevent of Qmainwindow...and set its position in statusbar !!:)
though it slows down moving of items in the view, it does solve the problem to some extent.... simple solution nah :D

jpn
8th November 2006, 08:41
#include <QtGui>

class MainWindow : public QMainWindow
{
public:
MainWindow(QWidget* parent = 0) : QMainWindow(parent)
{
QGraphicsScene* scene = new QGraphicsScene;
QGraphicsItem* item = scene->addText("Item");
item->setFlag(QGraphicsItem::ItemIsMovable);

view = new QGraphicsView(scene);
view->viewport()->installEventFilter(this);
// this is not actually even needed, QGraphicsView
// already sets the mouse tracking on on it's viewport
view->viewport()->setMouseTracking(true);
setCentralWidget(view);
}

bool eventFilter(QObject* object, QEvent* event)
{
if (event->type() == QEvent::MouseMove)
{
QMouseEvent* mouse = static_cast<QMouseEvent*>(event);
QPointF pos = view->mapToScene(mouse->pos());
statusBar()->showMessage(QString("(%1,%2)").arg(pos.x()).arg(pos.y()));
}
return false;
}

private:
QGraphicsView* view;
};

int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}

wysota
8th November 2006, 08:52
Subclassing the view and ignoring its mouse events (one has to specifically call ignore() on the event object in mouse event handlers) should work as well.

aamer4yu
8th November 2006, 10:11
@jpn

Thanks, ur solution is working fine...also the movement of items is smooth :)

I was also pretty much using the same code...


class CMainWindow : public QMainWindow
{
Q_OBJECT
public:
CMainWindow(QWidget *parent=0);
~CMainWindow();

private:
//void setupMatrix();
void populateScene();

CViewFrame *viewFrame; // CViewFrame derived from QFrame

//QGraphicsScene *scene;
CScene *scene;
QList<CMacro*> macroList;

protected:
bool eventFilter(QObject *obj, QEvent *event);
void mouseMoveEvent ( QMouseEvent * event );
void paintEvent(QPaintEvent *event);
};


CMainWindow::CMainWindow(QWidget *parent)
: QMainWindow(parent)
{
setMouseTracking(true);

populateScene();


viewFrame = new CViewFrame("demo",this);
viewFrame->getView()->setScene(scene);
viewFrame->getView()->setMouseTracking(true);

viewFrame->getView()->setSceneRect(-100,-100,1700,2500);
//setContentsMargins(200,200,600,600);

//scene->setBackgroundBrush(Qt::blue);


setCentralWidget(viewFrame);
viewFrame->getView()->installEventFilter(this);
//viewFrame->getView()->installEventFilter(this);
....
...
...



The only mistake was i was installing filter on view... rather than viewport :D
The events are now captured in QEvent::MouseMove of the filter...

So what does actually viewport act like ? why doesnt installing filter on view capture the events ??



@wysota

Ur solution too is working and short & elegant :)
Can u tell me more on event delegation ?? I saw thru the call stack and came to conclude that...that Qt uses QApplicationPrivate::notify_helper() to properly distrubute the events, and hence its View in the window that receives the events first.

but what will ignore do and how will the events propogate further ?? can u throw more light ?


Thanks a lot both of u guys...just wondering what took u so long to answer :D
neways it helped me in exploring & learning myself.

Thx again

wysota
8th November 2006, 10:33
Ur solution too is working and short & elegant :)
It wasn't my solution. Jpn already told you about it in his second post in this thread.


Can u tell me more on event delegation ?? I saw thru the call stack and came to conclude that...that Qt uses QApplicationPrivate::notify_helper() to properly distrubute the events, and hence its View in the window that receives the events first.
I can, but I doubt I can tell you more than you can read from the docs. In general the mechanism is simmilar to the one present in (for example) MFC - the events are propagated from class to class until one of them marks them as handled. In case of Qt the order is child widget -> its parent -> its parent -> ... -> application object.


but what will ignore do and how will the events propogate further ?? can u throw more light ?
I think I already answered that :)


Thanks a lot both of u guys...just wondering what took u so long to answer :D
Your question was answered at the very beginning, you just ignored that answer (instead of ignoring the event).

aamer4yu
8th November 2006, 10:46
Your question was answered at the very beginning, you just ignored that answer (instead of ignoring the event).

No, I didnt ignore that... as i said i installed filter on view...and tried all sort of things :D
i didt knew i had to install them on viewport...:crying:

earlier answers were like showing which tool to use... but didnt tell where to use :p
or may b i was ameatuer in Qt that i didnt understand what they meant :rolleyes:

wysota
8th November 2006, 11:17
Following the "ignore the event" link in JPN's post would have lead you to the right answer - event propagation.

aamer4yu
8th November 2006, 11:27
well i said, I had tried that too... but might be making some mistake somewhere...

neways dont fight... I take my thanks back from u :D ...
Jpn... double thnks to u :cool:

is that fine now wysota :P

wysota
8th November 2006, 12:08
is that fine now wysota :P

It's your call.

ranjithreddykommareddy
3rd December 2015, 05:04
hii....wysota .i am also having same problem with mouse events .now i am getting mouse events fine in QGraphicsscene .but i want to add a push button in form for mouse events to draw rectangle and it is moveble .so how can i proceed ..? can any one have idea...?

wysota
3rd December 2015, 07:12
hii....wysota .i am also having same problem with mouse events .now i am getting mouse events fine in QGraphicsscene .but i want to add a push button in form for mouse events to draw rectangle and it is moveble .so how can i proceed ..? can any one have idea...?

Show your (relevant) code, please.

ranjithreddykommareddy
3rd December 2015, 11:20
thanks for reply
bool Widget:: eventFilter(QObject* object, QEvent* event)
{


if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* mouse = static_cast<QMouseEvent*>(event);
if (ui->graphicsView->geometry().contains(mouse->pos()))
{
originpos = ui->graphicsView->mapToScene(mouse->pos());
// qDebug() << mouse->pos() << originpos ;
mousepress = true;
}
//statusBar()->showMessage(QString("(%1,%2)").arg(pos.x()).arg(pos.y()));


}
if(mousepress)
{
if (event->type() == QEvent::MouseMove)

{


QMouseEvent* mouse = static_cast<QMouseEvent*>(event);

if (ui->graphicsView->geometry().contains(mouse->pos()))
{
currentpos = ui->graphicsView->mapToScene(mouse->pos());
//qDebug() << mouse->pos() ;



if(!itemToDraw)
{
itemToDraw = new QGraphicsRectItem;

ui->graphicsView->scene()->addItem(itemToDraw);
itemToDraw->setPen(QPen(Qt::black, 1, Qt::SolidLine));


//itemToDraw->setPos(pos);
}
itemToDraw->setRect(originpos.x(),originpos.y(),
currentpos.x()- originpos.x(),
currentpos.y() - originpos.y());



}
//itemToDraw->setFlag(QGraphicsRectItem::ItemIsMovable);
}


}



if(mousepress)
{
if(event->type() == QEvent::MouseButtonRelease )
{
QMouseEvent* mouse = static_cast<QMouseEvent*>(event);
QPointF pos = ui->graphicsView->mapToScene(mouse->pos());
// qDebug() << pos ;
mousepress = false;

}
}



}