PDA

View Full Version : QTextEdit mouse movement filtering



been_1990
12th June 2010, 13:58
To filter the mouse events in a QTextEdit, do I have to subclass it and implement a custom filter to the class?
I've been trying to add an event filter to a QTextEdit I have placed on the ui, but I can't filter mouse events. I get all other events, but input events(mouse and keyboard).


moveFilter = new MoveEventFilter(ui->textEdit);
ui->textEdit->setMouseTracking(true);
ui->textEdit->installEventFilter(moveFilter);

MoveEventFilter.h:

#ifndef MOVEEVENTFILTER_H
#define MOVEEVENTFILTER_H
#include <QtGui>
#include <QDebug>

class MoveEventFilter : public QObject
{
Q_OBJECT

public:
MoveEventFilter(QTextEdit *parent){
//
canMove = false;
}
bool canMove;

private:
QPoint dragPosition;

protected:
bool eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseMove ){
qDebug() << obj->objectName();
}else{
qDebug() << obj->objectName() << event->type();
return QObject::eventFilter(obj, event);
}
}
};


#endif // MOVEEVENTFILTER_H

high_flyer
14th June 2010, 10:02
do I have to subclass it and implement a custom filter to the class?
no, using another object to filter events as you are trying is also an option.

You should at least get a compilation warning (if not an error) since your eventFilter() method doesn't return bool for all execution paths.
If you get a MouseMove event, the function returns nothing.
This will probably fix your problem as well.

been_1990
14th June 2010, 21:41
I get no errors whatsoever. It just seems that the filter can't get the mouse events.
I did a new project, but the results are the same:

widget.cpp:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);

moveFilter = new MoveEventFilter(this);
ui->textEdit->setMouseTracking(true);
ui->textEdit->installEventFilter(moveFilter);
setMouseTracking(true);
installEventFilter(moveFilter);
}

widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "moveEventFilter.h"

namespace Ui {
class Widget;
}

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

protected:
void changeEvent(QEvent *e);

private:
Ui::Widget *ui;
MoveEventFilter *moveFilter;
};

#endif // WIDGET_H

moveEventFilter.h:

#ifndef MOVEEVENTFILTER_H
#define MOVEEVENTFILTER_H
#include <QtGui>
#include <QDebug>

class MoveEventFilter : public QObject
{
Q_OBJECT

public:
MoveEventFilter(QWidget *parent){
//
canMove = false;
}
bool canMove;

private:
QPoint dragPosition;

protected:
bool eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseMove ){
qDebug() << "1111111111111";
return true;
}else{
qDebug() << obj->objectName() << event->type();
return QObject::eventFilter(obj, event);
}
}
};


#endif // MOVEEVENTFILTER_H

With that code I only filter mouse moves when directly on the widget, but not on the textEdit.

high_flyer
15th June 2010, 09:51
There is probably some simple error which I fail to see in your code.
You are complicating things however.
Usually the parent is used to filter events for children.
This means you can pass the QTextEdit its parent as en event filter, and implement the event filter in the parent.
This will save you the spacial class you made for this purpose.
But, as I said, I fail to see the mistake in your code... maybe some one with sharper eyes will ;-)

high_flyer
15th June 2010, 09:52
There is probably some simple error which I fail to see in your code.
You are complicating things however.
Usually the parent is used to filter events for children.
This means you can pass the QTextEdit its parent as en event filter, and implement the event filter in the parent.
This will save you the spacial class you made for this purpose.
But, as I said, I fail to see the mistake in your code... maybe some one with sharper eyes will ;-)

been_1990
16th June 2010, 00:00
But using the QTextEdit's parent as a event filter (and implement it) still does not catch mouse move on the QTextEdit, only when directly on the parent:

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->textEdit->setMouseTracking(true);
ui->textEdit->installEventFilter(this);
}

void Widget::mouseMoveEvent ( QMouseEvent * event ){
//bla bla bla.. code here
}

high_flyer
16th June 2010, 08:41
I could not understand your last sentence:
Does the code you posted last works for you or not?

been_1990
19th June 2010, 02:07
It doesn't. I still can't filter events on the QTextEdit.

agathiyaa
19th June 2010, 20:52
To filter the mouse events in a QTextEdit, do I have to subclass it and implement a custom filter

Yes. But you shall use your existing code with QTextEdit 's mouseMoveEvent reimplemented like the sample below. This would just propagate mouseMoveEvents and your existing event filter may work.



class MyTextEdit:public QTextEdit
{
public:
MyTextEdit(QWidget* parent):QTextEdit(parent)
{
}
protected:
void mouseMoveEvent(QMouseEvent* e)
{
QTextEdit::mouseMoveEvent(e);
e->ignore();

}
};

high_flyer
21st June 2010, 10:00
agathiyaa:
sub classing is an option, but it should not be necessary, if he only wants to filter normal (not sub classed) Qt events.
Event filtering is very easy and should work, there is a problem here that we don't see...

agathiyaa
21st June 2010, 10:15
@high_flyer -> My point is QWidgets mousemove events will be propogated to registered event filters, but QTextedits ( overidden) mouseMoveEvent will not propogate which in turn will not call the eventFilter. am i right ?

high_flyer
21st June 2010, 10:26
@high_flyer -> My point is QWidgets mousemove events will be propogated to registered event filters, but QTextedits ( overidden) mouseMoveEvent
Overridden mouse events?

been_1990
23rd June 2010, 22:58
I think he means that QTextEdit is not ment to let you filter it's mouse events, unless you subclass it. Is it that?

high_flyer
24th June 2010, 09:23
Well, if that is what he means- its not true, just so we are clear about it.

been_1990
24th June 2010, 23:47
Then why can't I filter mouse moves?

high_flyer
25th June 2010, 09:18
because something in your code is wrong,which we can't see.
If you create a minimal project that shows the problem and post it, I can try and run it, and see if I can find the problem.

JohannesMunk
25th June 2010, 17:48
Problem got my attention so I quickly implemented a test app.



#ifndef FILTER_H
#define FILTER_H

#include <QtCore>
#include <QtGui>
#include <QDebug>
#include <QtScript>

class MoveEventFilter : public QObject
{ Q_OBJECT

public:
MoveEventFilter(QWidget* parent = 0) : QObject(parent) {
canMove = false;
}
bool canMove;

protected:
bool eventFilter(QObject *obj, QEvent *event)
{
QMetaObject mo = QEvent::staticMetaObject;
qDebug() << obj->objectName() << mo.enumerator(mo.indexOfEnumerator("Type")).valueToKey(event->type());

if (event->type() == QEvent::MouseMove ){
QMouseEvent* me = static_cast<QMouseEvent*>(event);
qDebug() << QString("(%1|%2)").arg(me->pos().x()).arg(me->pos().y());
return true;
}

return QObject::eventFilter(obj, event);
}
};

class MouseTrack : public QLabel
{ Q_OBJECT
public:
MouseTrack(QWidget* parent = 0) : QLabel(parent) {
}
};

#endif // FILTER_H



#include <QtCore>
#include <QtGui>

#include "filter.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QWidget w;
QTextEdit* te = new QTextEdit();
te->setObjectName("textedit");

MouseTrack* mt = new MouseTrack();
mt->setMinimumHeight(100);
mt->setObjectName("MouseTrack");

MoveEventFilter* filter = new MoveEventFilter();

te->setMouseTracking(true);
te->installEventFilter(filter);
mt->setMouseTracking(true);
mt->installEventFilter(filter);

QVBoxLayout* vl = new QVBoxLayout();
vl->addWidget(te,0);
vl->addWidget(mt,1);
w.setLayout(vl);
w.show();

QObject::connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));

return a.exec();
}

If you play around with it a bit, you see that, that MouseMoves are filtered on the textedit, but only on the border!!

I guess the main text edit is some subwidget?

Joh

PS: I took the time and figured out how to convert those QEvent::type codes into readable names.

QEvent::staticMetaObject.enumerator(QEvent::static MetaObject.indexOfEnumerator("Type")).valueToKey(event->type());