2014-11-27 3 views
3


UI로 JavaFX를 사용하여 간단한 Java 트랜잭션 응용 프로그램을 만들려고합니다.
지금 내가하고 싶은 것은 1 개의 기본 단계와 많은 장면이있는 응용 프로그램에서 사용자 유휴 상태를 감지하는 것입니다.

예 : 사용자가 3 분 동안 유휴 상태이면 주 메뉴로 돌아갑니다.

JavaFX 유휴 상태를 감지하는 방법에 대한 웹 예제를 이미 시험해 보았습니다.하지만 발견 된 것은 항상 모든 장면에서 발생하는 유휴 상태 유휴 상태 감지입니다. (나는 생각합니다) 트랜잭션 응용 프로그램에 위험합니다 (예 : : 트랜잭션 처리 도중에 앱이 유휴 상태를 감지 함).
모든 단일 장면에서 사용자 유휴 상태를 감지 할 수 있습니까? 방법?
감사합니다.

편집 :JavaFX 2 사용자 유휴 감지

예를 들면 이미 시도 :

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

http://ochafik.com/blog/?p=98

+0

귀하의 질문은 명확하지 않습니다. 당신이 시도한 해결책을 보여주고 왜 그것이 당신을 위해 효과가 없는지 더 명확하게 설명 할 수 있습니까? –

답변

9

을 난 정말 당신이 트랜잭션에 대해 만들고있는 점을 이해하지 못하는 행동. 트랜잭션은 데이터에 대한 보장과 관련이 있으며 데이터 유실 상태에서 트랜잭션 동작을 정의해야하며 UI에서 발생한 일의 영향을받지 않아야합니다. 즉, 사용자가 유휴 상태로 설정되어 있어도 UI가 재설정 되더라도 사용자의 기본 동작은 완료되거나 롤백되어야합니다.

아마도 도움이 될 것입니다. (이 예제에서는 Java 8 코드를 사용했지만 JavaFX 2.2 호환이 필요한 경우 쉽게 만들 수 있습니다.) 이것은 유휴 검사를 구현하기 위해 Timeline을 사용한다는 점에서 Tomas Mikula의 일반적인 접근 방식을 따릅니다. Tomas의 FX Timer 래퍼는 사용하지 않았지만 원한다면 확실히 할 수 있습니다. 이 클래스는 사용자가 유휴 상태인지 여부에 대한 모니터를 캡슐화합니다. 모든 노드 (또는 장면) 및 이벤트 유형을 등록 할 수 있습니다. 해당 노드 (또는 장면)에서 해당 유형의 이벤트가 발생하면 사용자는 유휴 상태가 아닌 것으로 결정됩니다. 등록 된 이벤트가 발생하지 않고 지정된 시간이 경과하면 제공된 실행 파일이 실행됩니다 (FX 응용 프로그램 스레드에서). 이렇게하면 필요한 경우 다중 모니터를 작성하고 하나 이상의 노드를 각각 등록 할 수있는 유연성이 제공됩니다.

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에는 두 개의 탭이있는 탭 창이 있습니다 : 각각의 개별 탭은 "시작"버튼으로 시작한 다음 메인 컨텐츠에는 레이블, 텍스트 필드 및 버튼이 있습니다 .

각 탭 내용에는 연관된 유휴 모니터 (테스트 용 짧은)가 있습니다. 탭 내용의 모든 이벤트는 유휴 모니터를 재설정하지만 탭 내용 외부의 이벤트는 재설정하지 않습니다. 30 초 후에 전체 UI를 재설정하는 전체 창에 대한 "글로벌"유휴 모니터가 있습니다.

데이터가 보존된다는 점에 유의하십시오. 즉, 유휴 상태로 인해 시간이 초과되면 텍스트 입력란에 입력 한 텍스트가 올바르게 보존됩니다. 이것이 "거래"문제가 전혀 중요하지 않아야한다고 생각하는 이유입니다.

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

javaFX 2.0에서 이와 동일한 작업을 수행하고 메인 클래스에서 runnable을 전달하는 방법을 원하십니까? 너 나 좀 도와 줄 수있어? 나는 여기에 갇혀있다. IdleMonitor idleMonitor = 새로운 IdleMonitor (Duration.초 (30), "*****"true); ' –

+0

[익명 내부 클래스] (http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html) 구현을 사용하십시오. [lambda expression] 대신 Runnable (http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)을 참조하십시오. –