2016-10-07 2 views
0

JavaFX 응용 프로그램을 빌드 중이며 JavaFX UI에서 인수로 전달 된 값에 액세스하려고합니다. 어떤 이유로 든 기본 메소드 launchForm을 제외한 모든 메소드에서이 값에 액세스 할 수 없습니다. 다음은 내 코드의 모습입니다. JavaFX 메서드에서 매개 변수 사용

public class FormBuilder extends Application { 

    /* 
    * (non-Javadoc) 
    * @see javafx.application.Application#start(javafx.stage.Stage) 
    * Scene scene 
    *  Group root 
    *   BorderPane borderPane 
    *    TabPane tabPane 
    *     Tab stocksTab 
    *      BorderPane stockTabBorderPane 
    *       GridPane gridPane 
    *   
    */ 

    private Stocks stockData = new Stocks(); 
    private int size; 

    @Override 
    public void start(Stage stage) throws Exception { 
     stage.setTitle("Stock Manager"); 
     Group root = new Group(); 
     Scene scene = new Scene(root, 1024, 800, Color.WHITE); 

     TabPane tabPane = new TabPane(); 
     BorderPane borderPane = new BorderPane(); 
     BorderPane stockTabBorderPane = new BorderPane(); 

     Tab stocksTab = new Tab("Stocks"); 

     stockTabBorderPane.setTop(this.addHBox()); 
     stockTabBorderPane.setCenter(this.createGridPane()); 

     stocksTab.setContent(stockTabBorderPane); 
     tabPane.getTabs().add(stocksTab); 

     borderPane.setCenter(tabPane); 

     borderPane.prefHeightProperty().bind(scene.heightProperty()); 
     borderPane.prefWidthProperty().bind(scene.widthProperty()); 

     root.getChildren().add(borderPane); 


     stage.setScene(scene); 
     stage.show(); 


    } 

    private HBox addHBox() { 
     HBox hbox = new HBox(); 
     hbox.setPadding(new Insets(15, 12, 15, 12)); 
     hbox.setSpacing(10); 
     hbox.setStyle("-fx-background-color: #336699;"); 

     Button buttonCurrent = new Button("Current"); 
     buttonCurrent.setPrefSize(100, 20); 

     Button buttonProjected = new Button("Projected"); 
     buttonProjected.setPrefSize(100, 20); 
     hbox.getChildren().addAll(buttonCurrent, buttonProjected); 

     return hbox; 
    } 

    private GridPane createGridPane() { 

     GridPane gridPane = new GridPane(); 

     gridPane.setLayoutX(39); 
     gridPane.setLayoutY(131.0); 
     gridPane.setAlignment(Pos.TOP_CENTER); 
     gridPane.setVgap(5.0); 
     gridPane.setHgap(10.0); 

     gridPane.add(new Label("Active"), 1,1); 
     gridPane.add(new Label("Stock"), 2, 1); 
     gridPane.add(new Label("Symbol"), 3, 1); 
     gridPane.add(new Label("LPP"), 4, 1); 
     gridPane.add(new Label("LPP"), 5, 1); 
     gridPane.add(new Label("HPP"), 6, 1); 
     gridPane.add(new Label("LTP"), 7, 1); 

     System.out.println(this.size); 
     for(int v=2;v < this.stockData.getStocks().size()+2; v++) { 
      gridPane.add(new CheckBox(), 1, v); 
      gridPane.add(new Label("Amazon"), 2, v); 
      gridPane.add(new TextField(), 3,v); 
      gridPane.add(new TextField(), 4,v); 
      gridPane.add(new TextField(), 5,v); 
      gridPane.add(new TextField(), 6,v); 
      gridPane.add(new TextField(), 7,v); 

     } 

     return gridPane; 
    } 

    public void launchForm(Stocks stockData) { 
     this.stockData = stockData; 
     this.size = stockData.getStocks().size(); 
     System.out.println(stockData.getStocks().size()); 
     System.out.println(stockData.getStocks().get(0).getSector()); 
     launch(); 
    } 
} 

이제 문제는 내가 시도하고 createGridPane 방법 내에서 stockData 객체에서 값에 액세스 할 때, 값이 사용할 수없는 것입니다.

this.stockData.getStocks().size()

createGridPane 방법에서 0의 값을 제공한다. 그러나 launchForm 메서드에서 2의 값을 제공합니다.

다시 launchForm있어서의 값을 반환 "Retail"

this.stockData.getStocks().get(0).getSector() 

같은 다른 값이 존재한다. 그러나 동일한 클래스의 다른 메소드에서 동일한 메소드에 액세스하려고하면 예외가 발생합니다.

누군가 나를 도와 줄 수 있습니까?

+0

어디에서'launchForm'을 호출합니까? 그리고 왜 그 메소드 내부에서'launch()'를 호출하고 있습니까? ['launch()'] (http://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html#launch-java.lang.String...-)는 응용 프로그램을 시작합니다. 확실히 그 시점에서 응용 프로그램이 이미 시작되었습니다. JavaFX 라이프 사이클을 근본적으로 잘못 이해 했어야합니다. ['Application' docs] (http://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html) –

+0

나는 아마도 당신이하고있는 일에 관해서이 질문에 더 많은 정보를 포함시킬 필요가 있고 당신의 애플리케이션을 어떻게 구조화 했는지도 알 필요가 있습니다. –

답변

0

JavaFX에서는 기본적으로 Application 하위 클래스, 특히 start() 메서드를 응용 프로그램의 진입 점으로 간주해야합니다. 응용 프로그램 수명주기는 Application Javadocs에 설명되어 있지만 JavaFX 시작 프로세스는 정적 Application.launch(...) 메서드 중 하나를 호출하거나 JVM을 시작하고 기본 클래스로 Application 하위 클래스를 지정하여 (Oracle JDK를 사용하여) 시작됩니다 (심지어 main 메서드가없는 경우).다음

발사 과정 :

  1. Application 서브 클래스에 init()를 호출하는 Application 서브 클래스의 새로운 인스턴스를 생성하는 자바 FX 툴킷을 시작
  2. (기본 구현은 무 조작이됩니다)
  3. FX 응용 프로그램 스레드 시작
  4. Application 서브 클래스에서 start()을 호출합니다. exec FX 응용 프로그램 스레드에서 사용하십시오.

다른 스레드에서 호출되었지만 start()init()이 완료 될 때까지 호출되지 않을 것이 보장됩니다.

게시 한 코드에서 FormBuilder 클래스를 다른 곳에서 인스턴스화하고 해당 인스턴스에서 launchForm(...)을 호출해야합니다. launch()을 호출하면 위에서 설명한대로 두 번째 인스턴스가 만들어지고 start()이 호출됩니다. 따라서 launchForm(...)이 호출 된 인스턴스에서 설정 한 필드는 start(...)이 호출되는 인스턴스에 설정되지 않습니다.

당신도 FormBuilder 응용 프로그램의 엔트리 포인트가되도록 코드를 리팩토링, 또는 Application 서브 클래스하지 FormBuilder을 인스턴스화하고이를 사용하는 새로운 진입 점을 만들어야합니다. 데이터를로드하는 백그라운드 작업이있는 것으로 보입니다.이 클래스는 엔트리 포인트가 아니어야하는 별도의 클래스 여야합니다.

public class FormBuilder extends Application { 

    /* 
    * (non-Javadoc) 
    * @see javafx.application.Application#start(javafx.stage.Stage) 
    * Scene scene 
    *  Group root 
    *   BorderPane borderPane 
    *    TabPane tabPane 
    *     Tab stocksTab 
    *      BorderPane stockTabBorderPane 
    *       GridPane gridPane 
    *   
    */ 

    private Stocks stockData ; 
    private int size; 

    @Override 
    public void start(Stage stage) throws Exception { 

     StockDataAccessor stockDataAccessor = new StockDataAccessor(); 
     stockData = stockDataAccessor.getStocks(); 

     stage.setTitle("Stock Manager"); 
     Group root = new Group(); 
     Scene scene = new Scene(root, 1024, 800, Color.WHITE); 

     TabPane tabPane = new TabPane(); 
     BorderPane borderPane = new BorderPane(); 
     BorderPane stockTabBorderPane = new BorderPane(); 

     Tab stocksTab = new Tab("Stocks"); 

     stockTabBorderPane.setTop(this.addHBox()); 
     stockTabBorderPane.setCenter(this.createGridPane()); 

     stocksTab.setContent(stockTabBorderPane); 
     tabPane.getTabs().add(stocksTab); 

     borderPane.setCenter(tabPane); 

     borderPane.prefHeightProperty().bind(scene.heightProperty()); 
     borderPane.prefWidthProperty().bind(scene.widthProperty()); 

     root.getChildren().add(borderPane); 


     stage.setScene(scene); 
     stage.show(); 


    } 

    private HBox addHBox() { 
     HBox hbox = new HBox(); 
     hbox.setPadding(new Insets(15, 12, 15, 12)); 
     hbox.setSpacing(10); 
     hbox.setStyle("-fx-background-color: #336699;"); 

     Button buttonCurrent = new Button("Current"); 
     buttonCurrent.setPrefSize(100, 20); 

     Button buttonProjected = new Button("Projected"); 
     buttonProjected.setPrefSize(100, 20); 
     hbox.getChildren().addAll(buttonCurrent, buttonProjected); 

     return hbox; 
    } 

    private GridPane createGridPane() { 

     GridPane gridPane = new GridPane(); 

     gridPane.setLayoutX(39); 
     gridPane.setLayoutY(131.0); 
     gridPane.setAlignment(Pos.TOP_CENTER); 
     gridPane.setVgap(5.0); 
     gridPane.setHgap(10.0); 

     gridPane.add(new Label("Active"), 1,1); 
     gridPane.add(new Label("Stock"), 2, 1); 
     gridPane.add(new Label("Symbol"), 3, 1); 
     gridPane.add(new Label("LPP"), 4, 1); 
     gridPane.add(new Label("LPP"), 5, 1); 
     gridPane.add(new Label("HPP"), 6, 1); 
     gridPane.add(new Label("LTP"), 7, 1); 

     System.out.println(this.size); 
     for(int v=2;v < this.stockData.getStocks().size()+2; v++) { 
      gridPane.add(new CheckBox(), 1, v); 
      gridPane.add(new Label("Amazon"), 2, v); 
      gridPane.add(new TextField(), 3,v); 
      gridPane.add(new TextField(), 4,v); 
      gridPane.add(new TextField(), 5,v); 
      gridPane.add(new TextField(), 6,v); 
      gridPane.add(new TextField(), 7,v); 

     } 

     return gridPane; 
    } 

    // for non-JavaFX aware environments (like your IDE...) 
    public static void main(String[] args) { 
     launch(args); 
    } 
} 

그런 다음 당신이 필요로 할 것입니다 메인 클래스로 FormBuilder를 실행 : 같은

// class that reads data and encapsulates it as a Stocks object 

public class StockDataAccessor { 

    // ... 

    public Stocks getStocks() { 
     // ... 
    } 

} 

그런 다음 FormBuilder 보이는 : 그래서 첫 번째 리팩토링과 같을 것이다. 당신이 FormBuilder 클래스 중 응용 프로그램의 진입 점을 고려하려면


완전히 (매우 유사하다) 대체 리팩토링은 다음과 같습니다

public class FormBuilder { 

    /* 
    * (non-Javadoc) 
    * @see javafx.application.Application#start(javafx.stage.Stage) 
    * Scene scene 
    *  Group root 
    *   BorderPane borderPane 
    *    TabPane tabPane 
    *     Tab stocksTab 
    *      BorderPane stockTabBorderPane 
    *       GridPane gridPane 
    *   
    */ 

    private Stocks stockData ; 
    private int size; 

    private Group root ; 

    public FormBuilder() { 

     StockDataAccessor stockDataAccessor = new StockDataAccessor(); 
     stockData = stockDataAccessor.getStocks(); 

     root = new Group(); 

     TabPane tabPane = new TabPane(); 
     BorderPane borderPane = new BorderPane(); 
     BorderPane stockTabBorderPane = new BorderPane(); 

     Tab stocksTab = new Tab("Stocks"); 

     stockTabBorderPane.setTop(this.addHBox()); 
     stockTabBorderPane.setCenter(this.createGridPane()); 

     stocksTab.setContent(stockTabBorderPane); 
     tabPane.getTabs().add(stocksTab); 

     borderPane.setCenter(tabPane); 

     borderPane.prefHeightProperty().bind(scene.heightProperty()); 
     borderPane.prefWidthProperty().bind(scene.widthProperty()); 

     root.getChildren().add(borderPane); 



    } 

    public Parent getView() { 
     return root ; 
    } 

    private HBox addHBox() { 
     HBox hbox = new HBox(); 
     hbox.setPadding(new Insets(15, 12, 15, 12)); 
     hbox.setSpacing(10); 
     hbox.setStyle("-fx-background-color: #336699;"); 

     Button buttonCurrent = new Button("Current"); 
     buttonCurrent.setPrefSize(100, 20); 

     Button buttonProjected = new Button("Projected"); 
     buttonProjected.setPrefSize(100, 20); 
     hbox.getChildren().addAll(buttonCurrent, buttonProjected); 

     return hbox; 
    } 

    private GridPane createGridPane() { 

     GridPane gridPane = new GridPane(); 

     gridPane.setLayoutX(39); 
     gridPane.setLayoutY(131.0); 
     gridPane.setAlignment(Pos.TOP_CENTER); 
     gridPane.setVgap(5.0); 
     gridPane.setHgap(10.0); 

     gridPane.add(new Label("Active"), 1,1); 
     gridPane.add(new Label("Stock"), 2, 1); 
     gridPane.add(new Label("Symbol"), 3, 1); 
     gridPane.add(new Label("LPP"), 4, 1); 
     gridPane.add(new Label("LPP"), 5, 1); 
     gridPane.add(new Label("HPP"), 6, 1); 
     gridPane.add(new Label("LTP"), 7, 1); 

     System.out.println(this.size); 
     for(int v=2;v < this.stockData.getStocks().size()+2; v++) { 
      gridPane.add(new CheckBox(), 1, v); 
      gridPane.add(new Label("Amazon"), 2, v); 
      gridPane.add(new TextField(), 3,v); 
      gridPane.add(new TextField(), 4,v); 
      gridPane.add(new TextField(), 5,v); 
      gridPane.add(new TextField(), 6,v); 
      gridPane.add(new TextField(), 7,v); 

     } 

     return gridPane; 
    } 

} 

다음 진입 점을 만듭니다

public class StockApp extends Application { 

    @Override 
    public void start(Stage stage) { 
     FormBuilder formBuilder = new FormBuilder(); 
     Scene scene = new Scene(formBuilder.getView(), 1024, 800, Color.WHITE); 
     stage.setTitle("Stock Manager"); 
     stage.setScene(scene); 
     stage.show(); 
    } 

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

도움이되었고 문제를 해결할 수있었습니다. 고맙습니다. – ngnear

1

Application.launchlaunchForm 인스턴스 메소드에서 호출하고이 메소드가 응용 프로그램 클래스로 호출 된 인스턴스를 사용할 것으로 기대합니다.

그러나 JavaFX 시작은이 방법으로는 작동하지 않습니다. Application.launch가 호출되면

, 방법은 launch 방법 자체에 의해 만들어진에서 호출하고 initstart와 함께 사용이 새로운 인스턴스 클래스의 새로운 인스턴스입니다.

당신의 Stocks을 만들 수 있다면, 것이 문제를 해결하는 가장 쉬운 방법 init 또는 start (아마도 launch에 매개 변수로 일부 문자열을 전달).

그렇지 않으면 Application 하위 클래스의 새로 생성 된 인스턴스와 통신 할 다른 방법이 필요합니다. static members ...

+0

이것은'Application' 서브 클래스가 아니어야하고,'Stage' 서브 클래스 여야합니다 (또는'Stage'에 대한 참조가 있어야합니다). 그런 다음'launch()'를'show()'로 대체하십시오. –

+0

@James_D : OP가 새로운 인스턴스에서'start' 메서드가 호출되는 지점에 도달하면 플랫폼이 시작되지 않고'Stage'를 표시하려는 시도가 필연적으로 실패합니다 ... – fabian

+0

사실입니다. 그러나 여기서 라이프 사이클이 완전히 잘못되어있는 것처럼 보입니다. 분명히 다른 코드가'launchForm'을 호출하기 전에 실행 중입니다. 그 전에는 아무 것도 없어야합니다. 모든 시작 코드는 정말로 특별한 경우를 제외하고'init()'또는'start()'에 있어야합니다. (두 번째 문장에서 말한 것과 비슷합니다.) 그래서 "다른 코드"는'Application' 서브 클래스 여야하며,이 클래스는 다른 것이되어야합니다. 나는 OP가 게시 한 코드보다 구조적인 문제가 더 많다는 것을 의미한다고 생각한다. –