2016-10-07 6 views
0

Я создаю приложение JavaFX и хочу получить доступ к значениям, переданным в качестве аргумента в пользовательском интерфейсе JavaFX. По какой-то причине я не могу получить доступ к этим значениям во всех методах, кроме базового метода 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(); 
    } 
} 

Теперь вопрос заключается в том, что, когда я пытаюсь получить доступ к любому значению при stockData объекте в методе createGridPane значение не доступно.

Примерами являются

this.stockData.getStocks().size() дает значение 0 в методе createGridPane. Но он дает значение 2 в методе launchForm.

Опять же существуют и другие значения, такие как

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

, которая возвращает значение "Retail" в методе launchForm. Но когда я пытаюсь получить доступ к тому же в другом методе в одном классе, я получаю исключение.

Может кто-нибудь, пожалуйста, помогите мне здесь?

+0

Откуда вы вызываете 'launchForm'? И почему вы вызываете 'launch()' изнутри этого метода? ['launch()'] (http://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html#launch-java.lang.String...-) запускает приложение: конечно, приложение уже начато в этот момент. Я думаю, что вы, должно быть, неправильно поняли жизненный цикл JavaFX: см. Документы '' Application' (http://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html) –

+0

Я думаю, что вы вероятно, необходимо включить в этот вопрос больше информации о том, что вы делаете, и о том, как вы структурировали свое приложение. –

ответ

0

В JavaFX вы должны в основном рассмотреть подкласс Application, и в частности его метод start(), чтобы быть точкой входа приложения. Жизненный цикл приложения описан в Application Javadocs, но вкратце процесс запуска JavaFX инициируется либо путем вызова одного из статических методов Application.launch(...), либо (с использованием Oracle JDK) путем запуска JVM и определения подкласса Application как основного класса (даже если он не имеет метода main).

Процесс запуска затем:

  1. запускает инструментарий JavaFX
  2. создает новый экземпляр Application подкласса
  3. вызывает init() на Application подкласса (реализация по умолчанию является не-ор)
  4. начинает работу приложения FX
  5. вызывает start() на подклассе Application, exec используя его в потоке приложений FX.

Несмотря на то, вызывается на разных потоках, start() гарантированно не будет вызван до init() не завершена.

Из кода, который вы отправили, должен быть случай, когда вы создаете экземпляр класса FormBuilder в другом месте и вызываете launchForm(...) на этом экземпляре. Когда вы вызываете launch(), это создает второй экземпляр и вызывает на нем start(), как описано выше. Поэтому, конечно, поля, которые вы задали в экземпляре, на котором вызывается launchForm(...), не будут установлены в экземпляре, на который вызывается start(...).

Вы должны реорганизовать свой код так, что либо FormBuilder является точкой входа в приложение, или сделать FormBuilder не быть Application подкласса и создать новую точку входа, которая создает и использует его. Кажется, у вас есть некоторая фоновая работа, которая загружает данные: это должен быть отдельный класс, который не должен быть точкой входа. Таким образом, первый рефакторинга будет выглядеть следующим образом:

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

public class StockDataAccessor { 

    // ... 

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

} 

Тогда 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 в качестве основного класса будет делать то, что вам нужно.


Если вы хотите, чтобы учитывать точку входа приложения из в 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.launch в методе экземпляра launchForm и ожидаете, что он будет использовать экземпляр, для которого этот метод вызывается как класс приложения.

Запуск JavaFX не работает таким образом.

Если Application.launch это называют, нового экземпляра класса метод вызывается из создаются сам launch способом, и именно этот новый экземпляр, который используется с init и start.

Самый простой способ исправить это было бы, если бы вы могли создать Stocks в init или start (возможно прохождение некоторых строк в качестве параметров launch).

В противном случае вам понадобится другой способ связи с вновь созданным экземпляром подкласса Application, например. static членов ...

+0

Похоже, что это не должно быть подклассом «Приложение» вообще и должно быть подклассом «Этап» (или должно иметь ссылку на «Этап»). Затем просто замените 'launch()' на 'show()'. –

+0

@James_D: Если OP дошел до точки, в которой метод 'start' вызывается в новом экземпляре, платформа не была запущена, и любая попытка показать« этап »неизбежно завершится неудачно ... – fabian

+0

Это правда. Но похоже, что жизненный цикл здесь неправильный. Очевидно, что какой-то другой код выполняется до вызова 'launchForm'. Там действительно ничего не должно быть до этого; весь код запуска должен находиться в 'init()' или 'start()', за исключением действительно необычных обстоятельств. (Что похоже на то, что вы говорите в своем предпоследнем абзаце.) Таким образом, «другой код» должен быть подклассом «Приложение», и этот класс должен быть чем-то другим. Наверное, я имею в виду, что здесь есть больше структурных проблем, чем код, который опубликовал OP. –

Смежные вопросы