在JavaFX方法中使用参数

时间:2016-10-07 16:43:46

标签: java javafx

我正在构建一个JavaFX应用程序,我想访问在JavaFX UI中作为参数传递的值。出于某种原因,除了基本方法launchForm之外,我无法在所有方法中访问这些值。这是我的代码的样子。

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()createGridPane方法中给出值0。但它在launchForm方法中给出的值为2。

还有其他值,如

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

"Retail"方法中返回值launchForm。但是当我尝试在同一个类中以不同的方法访问它时,我得到一个例外。

有人可以帮我吗?

2 个答案:

答案 0 :(得分:1)

您正在Application.launch实例方法中调用launchForm,并期望它将此方法作为应用程序类使用的实例。

然而,JavaFX的推出并不是这样的。

如果调用Application.launch,则调用该方法的类的 new 实例由launch方法本身创建,并且它是使用的新实例使用initstart

解决此问题的最简单方法是,如果您可以在Stocksinit中创建start(可能会将某些字符串作为参数传递给launch)。

否则,您需要一些其他方式与新创建的Application子类实例进行通信,例如static成员......

答案 1 :(得分:0)

在JavaFX中,您基本上应该将Application子类,特别是其start()方法视为应用程序的入口点。应用程序生命周期在Application Javadocs中描述,但简而言之,JavaFX启动过程是通过调用其中一个静态Application.launch(...)方法或(使用Oracle JDK)启动,方法是启动JVM并指定Application子类作为主类(即使它没有main方法)。

然后启动过程:

  1. 启动JavaFX工具包
  2. 创建Application子类
  3. 的新实例
  4. init()子类上调用Application(默认实现是无操作)
  5. 启动FX Application Thread
  6. start()子类上调用Application,在FX应用程序线程上执行它。
  7. 尽管在不同的线程上调用,但在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);
        }
    }