如何在 Qt 中检测用户不活动?

发布于 2024-09-11 05:15:01 字数 542 浏览 13 评论 0原文

如何检测 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 吗?是否有更好的架构来检测用户活动?

How can I detect user inactivity in a Qt QMainWindow? My idea so far is to have a QTimer that increments a counter, which, if a certain value is passed, locks the application. Any mouse or key interaction should set the timer back to 0. However I need to know how to properly handle input events which reset; I can re-implement:

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)

...but won't the event handlers of all the widgets in the QMainWindow prevent events occurring in those controls from reaching the QMainWindow's? Is there a better architecture for detecting user activity as it is?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

仅一夜美梦 2024-09-18 05:15:01

您可以使用自定义事件过滤器来处理应用程序接收到的所有键盘和鼠标事件,然后再将其传递给子窗口小部件。

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 指出我之前的解决方案不是很有用。

You could use a custom event filter to process all keyboard and mouse events received by your application before they are passed on to the child widgets.

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);
  }
}

Then use something like

MyApplication app(argc, argv);
MyEventFilter filter;
app.installEventFilter(&filter);
app.exec();

This definitely works (I've tried it myself).

EDIT: And many thanks to ereOn for pointing out that my earlier solution was not very useful.

作死小能手 2024-09-18 05:15:01

更好的方法之一是捕获 xidle 信号,而不是捕获来自用户的大量事件。这里还需要捕获 QEvent:MouseMove 事件

One of better approach will be to catch xidle signal rather then catching so many events from user. Here one need to capture QEvent:MouseMove event also

挽清梦 2024-09-18 05:15:01

最干净的方法是重写主窗口小部件的 eventFilter 函数并将其设置为应用程序对象上的事件过滤器。

在过滤器内,您可以使用dynamic_cast来检查事件是否是QInputEvent。所有与用户交互的事件均源自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);
    }
};

您可以将基类 QWidget 替换为从 QWidget 派生的任何类。 (包括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);
    }
};

The cleanest way is to override the eventFilter function of your main window widget and set it as event filter on your application object.

Inside the filter you can use dynamic_cast to check if the event is a QInputEvent. All events with user interaction are derived from QInputEvent and are recognized this way.

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);
    }
};

You can replace the base class QWidget with any class derived from QWidget. (Including QMainWindow.) Note that the event function must pass the event to the base class, and return its return value.

If you have more then one window, you might also want to check, that the event target object is your window or one of its QWidget children.

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);
    }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文