2015-01-07 2 views
0

JavaFX 윈도우 객체를 인스턴스화하고 외부에서 업데이트 할 수있는 자체 스레드 (매우 자주, 초당 10-20 개)로 만들고 싶습니다. 이 창은 이미지를보고 다른 클래스에서 업데이트 할 수 있어야합니다.JavaFX 인스턴스화

Main 클래스

ImageViewer window = new ImageViewer("Preview"); 
window.show(); 
window.updateFrame(image); 

이미지 뷰어 클래스

public class ImageViewer extends Application{ 

private StackPane pane; 
private ImageView imgView; 
private Stage primaryStage; 

public ImageViewer() { 
} 

public void start(Stage primaryStage) { 
    this.primaryStage = primaryStage; 
    pane = new StackPane(); 
    imgView = new ImageView(); 
    pane.getChildren().add(imgView); 
    Scene scene = new Scene(pane); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 

public void updateFrame(Image image) { 
    imgView = new ImageView(image); 
} 

public void show() { Application.launch(); } 

생성자는 불행하게도 어떤 매개 변수를 사용하지 않고 내가이 개체의 모든 값을 설정하려고하면 아무 일도 발생하지 않는다. 왜 이런거야?

+0

'start (...)'메소드는 애플리케이션을 시작해야하는 곳입니다. 'Application.launch()'메소드는 당신을위한'Application' 서브 클래스의 인스턴스를 생성 할 것입니다. 애플리케이션의 다른 부분에서 재사용 할 클래스를 원한다면, 그것들은'Application'의 서브 클래스가되어서는 안됩니다. 이 응용 프로그램을 재구성해야 할 수도 있습니다. –

+0

더 자세히 설명해 주시겠습니까? 나는 JavaFX의 개념을 이해할 수 없다.이미지를로드하기 위해 메인 애플리케이션에서 창을 분리 (스레딩) 할 수 있습니까? – TomTom

+0

귀하의 질문은 실제로 이해가되지 않습니다. 거의 모든 UI 툴킷처럼 JavaFX는 단일 스레드이며 모든 UI 요소는 FX 응용 프로그램 스레드에서 액세스해야합니다. 당신이 묘사 한 앱을 어떻게 쓸 것인지에 대한 구조를 보여 주려고 노력할 것입니다. –

답변

2

Application 클래스는 전체 응용 프로그램을 나타내고, 그 start(...) 방법은 응용 프로그램이 시작될가 (당신이 정말로 기존의 Java 응용 프로그램에서 main(...) 방법의 동등한로 start(...) 방법을 생각해야한다)하는 방법입니다. 귀하의 질문은 당신이 Application 클래스가 창을 나타내는 것이라고 생각하는 것 같습니다; Stage 클래스는 윈도우를 나타냅니다. 그러나, 내가 말할 수있는 한, 귀하의 응용 프로그램은 어쨌든 하나의 창만 필요합니다.

당신이 Application.launch()이 (또는 Java 8 단지 메인 클래스로 Application 서브 클래스를 지정하는 JVM을 실행), 외환 툴킷이 Application 클래스 자체의 인스턴스를 생성 호출합니다 FX 툴킷 및 FX 응용 프로그램 스레드를 시작하고 통화 을 전달하여 Application 인스턴스에서 start(...) 메서드를 전달합니다. 당신은 자신의 Application 서브 클래스를 직접 인스턴스화해서는 안됩니다. 그럴 경우 start(...) 메서드가 호출 된 인스턴스와 다른 인스턴스를 갖게됩니다.

거의 모든 UI 툴킷과 마찬가지로 JavaFX는 단일 스레드입니다. "라이브"장면 그래프 요소에 대한 모든 작업은 JavaFX 응용 프로그램 스레드에서 실행해야합니다. 확실히 백그라운드 스레드를 가질 수는 있지만 UI를 업데이트해야하는 경우 Platform.runLater(...)을 호출하거나 javafx.concurrent API를 사용하여 FX 응용 프로그램 스레드에서 업데이트를 수행해야합니다. ("자신의 스레드에 JavaFX Window 객체가 있습니다."라는 말이 나에게도 의미가 없습니다. 스레드에는 객체가 없으며 객체는 힙에 있습니다. 스레드는 실행 가능 명령문의 독립적 인 시퀀스를 추상화 한 것입니다.) 이 같은

그래서 당신은 정기적으로 이미지보기에서 이미지를 업데이트하는 백그라운드 스레드를 위해 자바 FX 애플리케이션을 원한다면, 당신이 할 수있는 일 : 분명히

// imports omitted 

public class MyImageUpdatingApp extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     Label label = new Label("Main application"); 
     BorderPane root = new BorderPane(label); 
     Scene scene = new Scene(root, 600, 400); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 

     startImageUpdateThread(); 
    } 

    private void startImageUpdateThread() { 
     ImageView imageView = new ImageView(); 
     BorderPane root = new BorderPane(imageView); 
     Scene scene = new Scene(root, 600, 400); 
     Stage imageViewWindow = new Stage() 
     imageViewWindow.setScene(scene); 
     imageViewWindow.show(); 
     final int pause = 50 ; 
     Thread t = new Thread(() -> { 
      while (moreImagesToGet()) { 
       Image image = getNextImage() ; 
       Platform.runLater(() -> imageView.setImage(image)); 
       try { 
        Thread.sleep(pause); 
       } catch (Exception exc) { 
        exc.printStackTrace(); 
        break(); 
       } 
      } 
     }); 
     t.setDaemon(true); // this thread won't prevent application exit 
     t.setName("Image update thread"); 
     t.start(); 
    } 

    // ... 
} 

, 당신은에 startImageUpdateThread의 코드를 반영 할 수 원한다면 별도의 수업.

이 대답은 이미지를 생성하는 스레드와 UI 간의 관계를 보여주기위한 것입니다. 실생활에서는 이것을 적절하게 수행하기 위해보다 정교한 코드가 필요할 것입니다. 이미지를 충분히 빠르게 생성하고 표시 할 수있는 가능성은 희박하므로 이미지 버퍼를 사용하는 이미지 버퍼와 이미지를 생성하는 스레드가있는 BlockingQueue<Image>이 필요합니다.

+0

나는 더 명확하게 지금 본다. 감사. 그래도 질문을 따르겠습니다. JavaFX를 사용하려면 GUI가 항상 실제 프로그램이 아닌 기본 응용 프로그램이됩니까? 사실 여러 창이 필요합니다. 나는 그저'startImageUpdateThread'에 또 다른 무대를 넣고 그것을 얻기위한 이미지를 만드는 프로그램 클래스를 인스턴스화함으로써 그것을 할 수있었습니다. 그것이 어떻게 이루어지기 위해서입니까? – TomTom

+0

그게 대부분 맞습니다. '단계'는 창입니다. 더 많은 창을 만들려면 더 많은 '스테이지'를 인스턴스화하십시오. 그러나 당신은 당신의'Application' 클래스를 인스턴스화해서는 안됩니다. 'Application'은 당신의 "main class"와 같습니다. 시스템은 단지 당신을 위해 첫 번째 단계를 생성하고 편의상'start (...) '메서드에 전달합니다. 새 창을 만드는 방법에 대한 대답을 업데이트했습니다. –