Как обнаружить неактивность пользователя в Qt?
Как я могу обнаружить неактивность пользователя в Qt QMainWindow? Моя идея до сих пор состоит в том, чтобы иметь QTimer, который увеличивает счетчик, который, если передается определенное значение, блокирует приложение. Любое взаимодействие с мышью или клавишей должно установить таймер обратно на 0. Однако мне нужно знать, как правильно обрабатывать события ввода, которые сбрасываются; Я могу повторно реализовать:
virtual void keyPressEvent(QKeyEvent *event)
virtual void keyReleaseEvent(QKeyEvent *event)
virtual void mouseDoubleClickEvent(QMouseEvent *event)
virtual void mouseMoveEvent(QMouseEvent *event)
virtual void mousePressEvent(QMouseEvent *event)
virtual void mouseReleaseEvent(QMouseEvent *event)
... но не будут ли обработчики событий всех виджетов в QMainWindow предотвращать события, происходящие в этих элементах управления, до достижения QMainWindow? Есть ли лучшая архитектура для определения активности пользователей?
3 ответа
Вы можете использовать пользовательский фильтр событий для обработки всех событий клавиатуры и мыши, полученных вашим приложением, прежде чем они будут переданы дочерним виджетам.
class MyEventFilter : public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *ev)
{
if(ev->type() == QEvent::KeyPress ||
ev->type() == QEvent::MouseMove)
// now reset your timer, for example
resetMyTimer();
return QObject::eventFilter(obj, ev);
}
}
Тогда используйте что-то вроде
MyApplication app(argc, argv);
MyEventFilter filter;
app.installEventFilter(&filter);
app.exec();
Это определенно работает (я попробовал это сам).
РЕДАКТИРОВАТЬ: И большое спасибо ereOn за указание, что мое предыдущее решение было не очень полезным.
Один из лучших подходов - поймать сигнал xidle, а не поймать столько событий от пользователя. Здесь нужно также захватить событие QEvent:MouseMove
Самый чистый способ - переопределитьeventFilter
функцию вашего виджета главного окна и установите ее как фильтр событий для вашего объекта приложения.
Внутри фильтра вы можете использоватьdynamic_cast
чтобы проверить, является ли событие . Все события с взаимодействием с пользователем происходят изQInputEvent
и узнаются таким образом.
class MainWindow: public QWidget {
public:
MainWindow() {
QApplication::instance()->installEventFilter(this);
}
protected:
bool eventFilter(QObject* target, QEvent* event) override {
if(dynamic_cast<QInputEvent*>(event)){
// detected user interaction
}
return QWidget::eventFilter(target, event);
}
};
Вы можете заменить базовый класс любым классом, производным от . (ВключаяQMainWindow
.) Обратите внимание, чтоevent
функция должна передать событие базовому классу и вернуть его возвращаемое значение.
Если у вас более одного окна, вы также можете проверить, является ли целевой объект события вашим окном или одним из его окон.QWidget
дети.
class MainWindow: public QWidget {
public:
MainWindow() {
QApplication::instance()->installEventFilter(this);
}
protected:
bool eventFilter(QObject* target, QEvent* event) override {
if(dynamic_cast<QInputEvent*>(event) && (
target == this ||
findChildren<QWidget*>().contains(target))
){
// detected user interaction
}
return QWidget::eventFilter(target, event);
}
};