PDA

View Full Version : Inactivity tracker in QWidget



mustermann.klaus@gmx.de
28th April 2019, 01:04
Hallo everybody,

I created a widget with really a lot of elements of all kinds. All well sorted in layouts. The GUI has a central layout. Runs good. Now I want to close that widget automatically if the user goes cruising for burgers or 6 bud-light down on the corner - i.e. is inactive for - say 5 minutes.
Of course I would say


QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(close()));
timer.start(300000)


I did



void myWidget::mouseMoveEvent(QMouseEvent *e){
qDebug() << "mouse tracked";
resetMyTimer();
}


which gave me



Debugging starts
mouse tracked
mouse tracked
mouse tracked
mouse tracked
mouse tracked
Debugging has finished


All very good. But 99% of myWidget are covered by elements. Therefore mouse-events are hard to gain. How is the elegant way out of here?

Thanks and Cheers, Lars

Added after 4 minutes:

as always forgot to register for replies...

anda_skoa
28th April 2019, 11:26
You can install an event filter in the QApplication object.
See QObject::eventFilter().

It will "see" all events independent of the actual receiver.

Cheers,
_

mustermann.klaus@gmx.de
28th April 2019, 17:21
Hey anda_skoa,

Thumbs up!



int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
a.installEventFilter(&w);
w.show();

return a.exec();
}

In MainWindow:



bool MainWindow::eventFilter(QObject *obj, QEvent *event){

if (event->type() == QEvent::MouseMove) {
qDebug() << "Mouse filter tracked";
return true;
}
else{
return false;
}
}


very clearly trow:



Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked
Mouse filter tracked


Question, because I never used it: is it very expensive to do so?

Cheers, Lars

d_stranz
28th April 2019, 18:06
Question, because I never used it: is it very expensive to do so?

Not compared to a user's typical response time. Mouse signals are being propagated everywhere as your app runs and decisions being made - which widget is active, does it process the event or does its parent, map from global coordinates to widget coordinates, etc., etc. One more filter will add negligible delay.

Anda_skoa suggested installing the event filter on the QApplication instance. If you install it on the MainWindow as you have done, mouse events when a modal QDialog is active will not be seen by your filter, but would be seen by a filter installed on the application.

anda_skoa
28th April 2019, 20:06
Anda_skoa suggested installing the event filter on the QApplication instance. If you install it on the MainWindow as you have done, mouse events when a modal QDialog is active will not be seen by your filter, but would be seen by a filter installed on the application.

I was confused a bit as well, but actually this is correct.
The MainWindow object is the event filter and it is installed on the application object.

What I would suggest to do differently though is to always return "false".
I.e. the event filter is only "watching" move events, it doesn't "consume" them.

Cheers,
_

mustermann.klaus@gmx.de
29th April 2019, 16:31
Thanks for the replies. That's right d_stranz. But hovering over the modal window if open generates events. That would be sufficient for me. Anyway, just for the understanding, is that what you meant: ?


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

QApplication a(argc, argv);

MainWindow w;
w.installEventFilter(&a);
w.show();

return a.exec();
}


If so, where do I locate the SLOT, which I modified as follows:


// track user-interaction
bool MainWindow::eventFilter(QObject *obj, QEvent *event){

// check for specific content of "event" and react
if (event->type() == QEvent::KeyPress || event->type() == QEvent::MouseMove){
activityHappened = true;
}
// pass event to parent for further use
return QMainWindow::eventFilter(obj, event);
}


To me as a non prof that's a little confusing. Sorry again for that.


Thanks so much. Regards, Lars

d_stranz
29th April 2019, 19:44
The MainWindow object is the event filter and it is installed on the application object.

Ah, right you are. I misread the "a" for a "w". @mustermann - your original code is correct, my mistake.

mustermann.klaus@gmx.de
29th April 2019, 20:09
Feels good to hear that. As always thanks so much for the support.

Lars