Can't catch TapAndHoldGesture - qt

I grabGesture()ed one of my buttons:
buttons[0]->grabGesture(Qt::TapAndHoldGesture);
in the constructor, and declared:
bool event(QEvent *event);
in protected slots, and implemented it like this:
bool MyClass::event(QEvent *event)
{
if (event->type() == QEvent::Gesture){
QGestureEvent *gestevent = static_cast<QGestureEvent *>(event);
if (QGesture *gest = gestevent->gesture(Qt::TapAndHoldGesture)){
QTapAndHoldGesture *tapgest = static_cast<QTapAndHoldGesture *>(gestevent->gesture(Qt::TapAndHoldGesture));
cout << "grabbed a gesture event" << endl;
}
return true;
}
cout << "not a gesture event" << endl;
return QWidget::event(event);
}
and I keep getting "not a gesture event" printed to screen however I press (normal press / long press / ... )
What I'm trying to do is a long key press (from the keyboard)
It's said in the Qt Documentation:
A gesture could be a particular movement of a mouse, a touch screen
action, or a series of events from some other source. The nature of
the input, the interpretation of the gesture and the action taken are
the choice of the developer.
So I suppose also a keyboard can trigger QGesture events.

If the class handling the grap (MyClass) event is not the class where the gesture is detected on (QPushButton assuming buttons[0] is a QPushButton), then you need and event filter:
buttons[0]->grabGesture(Qt::TapAndHoldGesture);
buttons[0]->installEventFilter( myClass ); // myClass being a MyClass instance
Now, myClass object will be forwarded all events from buttons[0], this is done using QObject::eventFilter virtual function:
bool MyClass::eventFilter(QObject *obj, QEvent *event)
{
if ( event->type() == QEvent::Gesture && obj == buttons[0] )
{
QGestureEvent *gestevent = static_cast<QGestureEvent *>(event);
if (QGesture *gest = gestevent->gesture(Qt::TapAndHoldGesture)){
QTapAndHoldGesture *tapgest = static_cast<QTapAndHoldGesture *>(gestevent->gesture(Qt::TapAndHoldGesture));
cout << "grabbed a gesture event" << endl;
return true;
}
}
// standard event processing
return Parent::eventFilter(obj, event); // Parent being MyClass parent type, maybe QDialog or QWidget
}

Related

QPlainTextEdit double click event

I need to capture the double click event on a QPlainTextEdit that is inside a QDockWidget.
In my actual code I have installed an event filter in the QDockWidget, to handle resize operations, and in the QPlainTextEdit, to handle the double click events:
// Resize eventfilter
this->installEventFilter(this);
ui->myPlainTextEdit->installEventFilter(this);
But, although it works for the QDockWidget I am unable to catch the double click event for the QPlainTextEdit:
bool MyDockWidget::eventFilter(QObject *obj, QEvent *event) {
if (event->type() == QEvent::Resize && obj == this) {
QResizeEvent *resizeEvent = static_cast<QResizeEvent*>(event);
qDebug("Dock Resized (New Size) - Width: %d Height: %d",
resizeEvent->size().width(),
resizeEvent->size().height());
} else if (obj == ui->myPlainTextEdit && event->type() == QMouseEvent::MouseButtonDblClick) {
qDebug() << "Double click";
}
return QWidget::eventFilter(obj, event);
}
With this code the message "Double click" is never shown. Any idea what is wrong with the code?
QTextEdit inherits a QScrollView and when you double click on the viewport of the QTextEdit, the viewport receives the double click event. You can cross check your current code by double clicking on the edges of the text edit. It will capture the event.
To solve this, add the event filter to the view port in addition to the current event filters you have installed as shown below:
ui->myPlainTextEdit->viewport()->installEventFilter(this);
Next, capture the event using this if statement:
if ((obj == ui->myPlainTextEdit||obj==ui->myPlainTextEdit->viewport()) &&
event->type() == QEvent::MouseButtonDblClick)
{
qDebug() << "Double click"<<obj->objectName();
}
You can capture the click position using QMouseEvent:
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
qDebug()<<QString("Click location: (%1,%2)").arg(mouseEvent->x()).arg(mouseEvent->y());

MouseDrag on child widgets

I am following this instructions to get the child events. My aim is to change the value of QSpinBox by dragging the mouse up/down by keeping the Ctrl key pressed (like in GIMP).
However, while this works for the window, QSpinBox ignores the drag and just selects the contents inside.
I have installed the eventfilter into all childs with:
eventFilter(QObject *obj, QEvent *event)
{
switch(event->type())
{
case QEvent::ChildAdded:
{
QChildEvent* ce = static_cast<QChildEvent*>(event);
// Install the filter to each new child object created
ce->child()->installEventFilter(this);
break;
}
case QEvent::ChildRemoved:
{
QChildEvent* ce = static_cast<QChildEvent*>(event);
// Remove the the filter from each new child object removed
ce->child()->removeEventFilter(this);
break;
}
case QEvent::MouseButtonPress:
{
QMouseEvent* me = static_cast<QMouseEvent*>(event);
qDebug() << QString::number(me->pos().x());
qDebug() << QString::number(me->pos().y());
return true;
}
case QEvent::MouseButtonRelease:
{
QMouseEvent* me = static_cast<QMouseEvent*>(event);
qDebug() << QString::number(me->pos().x());
qDebug() << QString::number(me->pos().y());
return true;
}
case QEvent::MouseMove:
{
QMouseEvent* me = static_cast<QMouseEvent*>(event);
qDebug() << QString::number(me->pos().x());
qDebug() << QString::number(me->pos().y());
return true;
}
}
return QWidget::eventFilter(obj, event);
}
and in the constructor using:
setMouseTracking(true);
installEventFilter(this);
How can I fully make QSpinBox ignore selection?

Long Mouse Press on QToolButton calls the released signal

I have a QToolButton defined. I have written two slots for pressed and released signals.
void EyImgGalleryWindow::toolPressed()
{
if(Uptimer->timerId() == -1)
Uptimer->start();
m_CustomGalleryView->scrollUp();
}
void EyImgGalleryWindow::toolReleased()
{
Uptimer->stop();
m_CustomGalleryView->scrollUpRelease();
}
When the pressed() signal is emitted, I am starting a timer and when the released signal is emitted I am stopping the timer.
So here my implementation is when the timer exceeds 3s I am updating a variable. I have to update the variable only when the User have a long press on this QToolButton.
But here my implementation is failing in this case. When I have a long press on QToolButton, It is emitting the Pressed and Released signal on equal intervals. When a long press is there we should get only once the Released signal and Why here it is calling the Released signal multiple times. Is there anything i am doing wrong here?
You can catch long press with next event filter and QElapsedTimer:
QElapsedTimer el;//somewhere
//...
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if(obj == ui->pushButton_13 && event->type() == QEvent::MouseButtonPress)
{
el.start();
}
if(obj == ui->pushButton_13 && event->type() == QEvent::MouseButtonRelease)
{
qDebug() << el.elapsed();//in milliseconds, you can divide by 1000 to get seconds
if(el.elapsed() > 1000)
qDebug() << "long";
else
qDebug() << "not long";
}
return QObject::eventFilter(obj, event);
}
It will work for pushButtons, labels, toolButtons etc.

onmouseover and click event QLineEdit

How can I define onmouseover and click event for a QLineEdit? I want to make 2 signals as onmouseover() and clicked() for QLineEdit
You can install an event filter on your QLineEdit.
Here's an example:
QLineEdit *line_edit = new QLineEdit(this);
ui->verticalLayout->addWidget(line_edit);
line_edit->installEventFilter(this);
And in your event filter function you can do something like this: (This is a function you override)
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::MouseButtonPress)
{
qDebug() << "CLICK";
}
if(event->type() == QEvent::MouseMove)
{
qDebug() << "MOUSE OVER";
}
return false;
}
I'm afraid, you'll have to inherit QLineEdit and override void mouseMoveEvent ( QMouseEvent * event ) and void mousePressEvent ( QMouseEvent * event ) (or void mouseReleaseEvent ( QMouseEvent * event ) if you wish). And don't forget to call setMouseTracking(true); to track mouse moves, when no mouse button is held.

How can I make a QWidget semitransparent to events?

I've seen similar questions but no answers that fit what I need. I want an invisible widget that lives on top of my whole application (no problems here). I want this widget to catch events so that I can print stuff about them, record them, whatever. I currently have an event filter hooked up that does this just fine. Then I want it to let the event go through to whatever is behind the widget. So for instance, if I try to push a button, the invisible widget should notice that a press happened on that spot, and then the button should actually be pressed. Can this be done in a simple way, or am I going to have to write code to simulate all the events beneath the invisible widget?
From all the information you disclosed in the comments, I suggest you filter the event as previously discussed, and then use QCoreApplication::sendEvent to forward the desired events to the invisible widget. It will then propagate the event accordingly to its children.
EDIT: OK, here is quick example that includes a QObject based event filter, that will filter the events for a widget, if the event is mouse event, it will be left for the widget to handle and print the output, if the event is a key event, it will be filtered and not forwarded back to the widget:
The event filter class:
class EventInfo : public QObject {
Q_OBJECT
public:
explicit EventInfo(QObject *parent = 0) : QObject(parent) {}
bool eventFilter(QObject *, QEvent *e) {
if (e->type() == QEvent::MouseButtonRelease){
qDebug() << "click event not filtered";
return false;
}
if (e->type() == QEvent::KeyRelease) {
QKeyEvent *event = static_cast<QKeyEvent *>(e);
if (event) qDebug() << "key" << event->key() << "filtered";
return true;
}
return false;
}
};
The widget:
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget *parent = 0) : QWidget(parent) {}
protected:
void mouseReleaseEvent(QMouseEvent *e) {
qDebug() << "widget clicked at position" << e->pos();
}
void keyReleaseEvent(QKeyEvent *e) {
qDebug() << "pressed key" << e->key();
}
};
main.cpp:
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
Widget w;
EventInfo info;
w.installEventFilter(&info);
w.show();
return a.exec();
}
Testing output to show that keyboard events are filtered and mouse press events are forwarded to the widget:
click event not filtered
widget clicked at position QPoint(352,230)
key 70 filtered
click event not filtered
widget clicked at position QPoint(405,163)
key 87 filtered

Resources