JavaFX 2用户空闲检测 [英] JavaFX 2 User Idle Detection

查看:152
本文介绍了JavaFX 2用户空闲检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我正在尝试使用JavaFX作为UI创建一个简单的Java事务应用程序。

我现在要做的是从我的应用程序中检测用户空闲状态,该应用程序有1个主要阶段和许多场景。


示例:如果用户空闲3分钟然后返回主菜单。


我已经在网上尝试了一些关于如何检测JavaFX空闲状态的例子,但我发现总是-one function idle state detection正在发生所有场景 - 对于交易应用程序而言(我认为)危险的方法(例如:应用程序在事务处理过程中检测空闲状态)。

可以在每个场景中检测用户空闲状态吗?怎么样?

谢谢。



编辑:

我已尝试的示例:

http://tomasmikula.github.io/blog/2014/06/04/timers-in-javafx-and-reactfx.html

http://ochafik.com/博客/?p = 98

推荐答案

我真的不明白你对交易行为的看法。事务涉及对数据的保证,您的事务行为应该在数据级别定义,不应受UI中发生的事件的影响。换句话说,即使由于用户空闲而重置UI,您的原子行为也应该完成或回滚。

I don't really understand the point you are making about transactional behavior. Transactions concern guarantees about the data, and your transactional behavior should be defined at the data level and should not be impacted by what is happening in the UI. In other words, your atomic behavior should complete or rollback even if the UI resets due to the user being idle.

但是,这可能会有所帮助。 (注意我在这些示例中使用了Java 8代码,但如果需要,您可以相当容易地使其符合JavaF 2.2。)这遵循Tomas Mikula的一般方法,因为它使用时间轴实施空闲检查。我没有使用Tomas的FX Timer包装器,但如果你愿意,你当然可以这样做。此类封装了一个监视器,以确定用户是否处于空闲状态。您可以注册任何节点(或场景)和事件类型:如果该节点(或场景)上发生该类型的事件,则确定用户不空闲。如果指定的时间过去而没有发生任何已注册的事件,则执行提供的runnable(在FX Application Thread上)。这使您可以灵活地创建多个监视器(如果需要),并为每个监视器注册一个或多个节点。

Maybe this will help, though. (Note I used Java 8 code in these examples, but you can fairly easily make it JavaF 2.2 compliant if you need.) This follows Tomas Mikula's general approach in that it uses a Timeline to implement the idle check. I didn't use Tomas' FX Timer wrapper but you could certainly do so if you like. This class encapsulates a monitor for whether the user is idle. You can register any node (or scene) and type of event: if an event of that type occurs on that node (or scene), the user is determined not to be idle. If the specified time elapses without any registered events occurring, the provided runnable is executed (on the FX Application Thread). This gives you the flexibility to create multiple monitors, if needed, and to register one or more nodes with each.

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.scene.Node;
import javafx.scene.Scene;

import javafx.util.Duration;

public class IdleMonitor {

    private final Timeline idleTimeline ;

    private final EventHandler<Event> userEventHandler ;

    public IdleMonitor(Duration idleTime, Runnable notifier, boolean startMonitoring) {
        idleTimeline = new Timeline(new KeyFrame(idleTime, e -> notifier.run()));
        idleTimeline.setCycleCount(Animation.INDEFINITE);

        userEventHandler = e -> notIdle() ; 

        if (startMonitoring) {
            startMonitoring();
        }
    }

    public IdleMonitor(Duration idleTime, Runnable notifier) {
        this(idleTime, notifier, false);
    }

    public void register(Scene scene, EventType<? extends Event> eventType) {
        scene.addEventFilter(eventType, userEventHandler);
    }

    public void register(Node node, EventType<? extends Event> eventType) {
        node.addEventFilter(eventType, userEventHandler);
    }

    public void unregister(Scene scene, EventType<? extends Event> eventType) {
        scene.removeEventFilter(eventType, userEventHandler);
    }

    public void unregister(Node node, EventType<? extends Event> eventType) {
        node.removeEventFilter(eventType, userEventHandler);
    }

    public void notIdle() {
        if (idleTimeline.getStatus() == Animation.Status.RUNNING) {
            idleTimeline.playFromStart();
        }
    }

    public void startMonitoring() {
        idleTimeline.playFromStart();
    }

    public void stopMonitoring() {
        idleTimeline.stop();
    }
}

这是一个测试。 开始按钮可能是用于登录的替身。主UI有一个带有两个选项卡的选项卡窗格:每个单独的选项卡以其自己的开始按钮开始,然后主要内容具有标签,文本字段和按钮。

Here's a test. The "Start" buttons are perhaps stand-ins for logging in. The main UI has a tab pane with two tabs: each individual tab starts with its own "Start" button and then the main content has a label, text field, and button.

每个标签内容都有一个(短的,用于测试)空闲监视器与它们相关联。选项卡内容上的任何事件都将重置空闲监视器,但选项卡内容之外的事件不会重置它。整个窗口还有一个全局空闲监视器,它会在30秒后重置整个UI。

The tab contents each have a (short, for testing) idle monitor associated with them. Any event on the content of the tab will reset the idle monitor, but events outside of the tab content will not reset it. There's also a "global" idle monitor for the entire window which resets the whole UI after 30 seconds.

请注意,数据会被保留:即如果由于空闲,您在文本字段中键入的任何文本都会正确保留。这就是为什么我认为交易的问题根本不重要。

Note that the data is preserved: i.e. if you timeout due to the idle, any text you type in the text field is preserved properly. This is why I think the issue with "transactions" should not matter at all.

import javafx.application.Application;
import javafx.event.Event;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

public class IdleTest extends Application {

    @Override
    public void start(Stage primaryStage) {

        StackPane root = new StackPane();

        Parent mainUI = buildMainUI();
        Scene scene = new Scene(root, 350, 150);
        Parent startUI = buildStartUI(() -> root.getChildren().setAll(mainUI));
        root.getChildren().add(startUI);

        IdleMonitor idleMonitor = new IdleMonitor(Duration.seconds(30),
                () -> root.getChildren().setAll(startUI), true);
        idleMonitor.register(scene, Event.ANY);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Parent buildStartUI(Runnable start) {
        Button button = new Button("Start");
        button.setOnAction(e -> start.run());
        StackPane root = new StackPane(button);
        return root ;
    }

    private Parent buildMainUI() {
        TabPane tabPane = new TabPane();
        Tab tab1 = new Tab("One");
        Parent tab1Content = buildTabUI("Tab 1");
        Parent tab1StartContent = buildStartUI(() -> tab1.setContent(tab1Content));
        tab1.setContent(tab1StartContent);
        IdleMonitor tab1IdleMonitor = new IdleMonitor(Duration.seconds(5), 
                () -> tab1.setContent(tab1StartContent), true);
        tab1IdleMonitor.register(tab1Content, Event.ANY);

        Tab tab2 = new Tab("Two");
        Parent tab2Content = buildTabUI("Tab 2") ;
        Parent tab2StartContent = buildStartUI(() -> tab2.setContent(tab2Content));
        tab2.setContent(tab2StartContent);
        IdleMonitor tab2IdleMonitor = new IdleMonitor(Duration.seconds(10),
                () -> tab2.setContent(tab2StartContent), true);
        tab2IdleMonitor.register(tab2Content, Event.ANY);

        tabPane.getTabs().addAll(tab1, tab2);
        return tabPane ;
    }

    private Parent buildTabUI(String text) {
        Button button = new Button("Click here");
        button.setOnAction(e -> System.out.println("Click in "+text));
        VBox content = new VBox(10, new Label(text), new TextField(), button);
        content.setAlignment(Pos.CENTER);
        return content ;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

这篇关于JavaFX 2用户空闲检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆