2012-11-30 4 views
0

JavaFX 응용 프로그램에 카운터를 구현하고 싶습니다. 동작은 단순히 버튼을 통해 제어된다 :다른 스레드에서 카운트 다운 제어

먼저 버튼은 사용자가 클릭 한 후 카운트 다운이 10, 9, 8, ...,
  • 0은 사용자가 클릭 할 때 카운트 다운을 시작
    1. 카운트 다운 중에 버튼, 카운트 다운이 사용자가 카운트 다운 동안 10

    에 의해 시작 다시 카운트 다운을 실행할 수 있어야합니다 2. 후

  • 을 취소해야, 일부 무거운 수학 컴퓨팅은 내 응용 프로그램 오디오 분석에 (처리).

    올바른 방법으로 수행한다면 내 소스 코드를 살펴볼 수 있습니까? 특히 또는 CountdownViewPlatform.runLater 항목을 사용해야하며 간단한 Java Thread을 사용할 수 있습니까? 아니면 JavaFX Service/Task 클래스를 사용해야합니까? 어떤 제안이라도 환영합니다.

    1. CountdownTest : 자바 FX를 스테이지를 생성하고 시작)
    2. CountdownView :

      응용 프로그램이 3 개 요소로 나누어 져 싱글, 간단한 버튼이 포함은 CountdownController

    3. CountdownController에 버튼 이벤트를 전달합니다 싱글을 새로운 Thread을 시작합니다. Thread 내에서 카운트 다운이 수행되고 CountdownView은 새로운 카운트 다운 상태를 보여주기 위해 업데이트되며 일부 수학 자료가 처리됩니다.

    CountdownTest.java

    package org.example; 
    
    import javafx.application.Application; 
    import javafx.scene.Group; 
    import javafx.scene.Scene; 
    import javafx.stage.Stage; 
    
    public class CountdownTest extends Application { 
        @Override 
        public void start(Stage primaryStage) throws Exception { 
         final Group root = new Group(); 
         final Scene scene = new Scene(root); 
         root.getChildren().setAll(CountdownView.getInstance()); 
         primaryStage.setScene(scene); 
         primaryStage.show(); 
        } 
    
        @Override 
        public void stop() throws Exception { 
         super.stop(); 
         CountdownController.getInstance().stop(); 
        } 
    
        public static void main(String[] args) { 
         launch(args); 
        } 
    } 
    

    CountdownView.java

    package org.example; 
    
    import javafx.event.EventHandler; 
    import javafx.scene.Group; 
    import javafx.scene.control.Button; 
    import javafx.scene.control.Tooltip; 
    import javafx.scene.input.MouseEvent; 
    
    public final class CountdownView extends Group { 
        private static final CountdownView instance = new CountdownView(); 
    
        private Button start; 
    
        private CountdownView() { 
         start = new Button("Start"); 
         start.setTooltip(new Tooltip("click to start countdown")); 
         start.setOnMouseClicked(new EventHandler<MouseEvent>() { 
          @Override 
          public void handle(MouseEvent event) { 
           CountdownController.getInstance().onStartClick(); 
          } 
         }); 
    
         this.getChildren().setAll(start); 
        } 
    
        public void startCountdown() { 
         System.out.println("startCountdown"); 
         start.setTooltip(new Tooltip("click to stop countdown")); 
        } 
    
        public void setCountdown(final int countdown) { 
         System.out.println("setCountdown " + countdown); 
         start.setText(String.valueOf(countdown)); 
        } 
    
        public void reset() { 
         System.out.println("reset"); 
         start.setText("Start"); 
         start.setTooltip(new Tooltip("click to start countdown")); 
        } 
    
        public static CountdownView getInstance() { 
         return instance; 
        } 
    } 
    

    CountdownController.java

    package org.example; 
    
    import javafx.application.Platform; 
    
    public final class CountdownController { 
        private static final CountdownController instance = new CountdownController(); 
    
        private Thread countdownThread; 
        private volatile boolean running = false; 
    
        public void onStartClick() { 
         if (!running) { 
          countdownThread = new Thread(new Runnable() { 
           @Override 
           public void run() { 
            running = true; 
            int countdown = 10; 
            Platform.runLater(new Runnable() { 
             @Override 
             public void run() { 
              CountdownView.getInstance().startCountdown(); 
              CountdownView.getInstance().setCountdown(10); 
             } 
            }); 
            final long start = System.currentTimeMillis(); 
            int lastCountdown = countdown; 
            while (!Thread.interrupted() && countdown > 0) { 
             countdown = (int) (10 - (System.currentTimeMillis() - start)/1000); 
             if (countdown != lastCountdown) { 
              lastCountdown = countdown; 
              final int currentCountdown = countdown; 
              Platform.runLater(new Runnable() { 
               @Override 
               public void run() { 
                CountdownView.getInstance().setCountdown(
                  currentCountdown); 
               } 
              }); 
             } 
    
             // Do some heavy computing stuff 
             for (int i = 0; i < 10000000; i++) { 
              Math.sin(Math.random()); 
             } 
            } 
            running = false; 
            Platform.runLater(new Runnable() { 
             @Override 
             public void run() { 
              CountdownView.getInstance().reset(); 
             } 
            }); 
           } 
          }); 
          countdownThread.start(); 
         } else { 
          countdownThread.interrupt(); 
         } 
        } 
    
        public void stop() { 
         if (countdownThread != null) { 
          System.out.println("stop"); 
          countdownThread.interrupt(); 
         } 
        } 
    
        public static CountdownController getInstance() { 
         return instance; 
        } 
    } 
    
    ,
  • +0

    참조 http://codeReview.stackexchange.com –

    +0

    JB Nizet에게 감사드립니다. 다음 번에는 _codereview.stackexchange_를 염두에 두겠습니다. – Vertex

    답변

    1

    지나치게 땀을 내지 마십시오. 태스크와 서비스 클래스는 유언 집행자를 대상으로 구축 된 일부 유틸리티이며, 제공해야 할 것이 필요하지 않은 경우 추가 작업 일뿐입니다.

    컨트롤러를 사용하여 어떤 스레드를 실행해야할지 결정하는 것이 정확하다고 생각하면 구성 요소와 컨트롤러간에 라우팅 메시지를 충분히 처리 할 수 ​​있습니다.

    +0

    감사합니다, Andy Till! 그리고 질문에, 컨트롤러 또는 뷰에서'Platform.runLater'를 호출하십시오 : 나는'Platform.runLater' 호출이 컨트롤러 컴포넌트에 나타나야한다고 생각합니다. 보기 구성 요소가 JavaFX-UI 구성 요소 ('확장 그룹 ')이고 UI 변경 사항이 JavaFX 응용 프로그램 스레드에 나타나야하기 때문입니다. 따라서 컨트롤러 구성 요소는'Platfrom.runLater'를 통해이 스레드에서 뷰의 변경 사항을 실행해야합니다. – Vertex

    +0

    컨트롤러에 스레딩을 유지해야하는 또 다른 이유가 있습니다. –