我正在构建一个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
。但是当我尝试在同一个类中以不同的方法访问它时,我得到一个例外。
有人可以帮我吗?
答案 0 :(得分:1)
您正在Application.launch
实例方法中调用launchForm
,并期望它将此方法作为应用程序类使用的实例。
然而,JavaFX的推出并不是这样的。
如果调用Application.launch
,则调用该方法的类的 new 实例由launch
方法本身创建,并且它是使用的新实例使用init
和start
。
解决此问题的最简单方法是,如果您可以在Stocks
或init
中创建start
(可能会将某些字符串作为参数传递给launch
)。
否则,您需要一些其他方式与新创建的Application
子类实例进行通信,例如static
成员......
答案 1 :(得分:0)
在JavaFX中,您基本上应该将Application
子类,特别是其start()
方法视为应用程序的入口点。应用程序生命周期在Application
Javadocs中描述,但简而言之,JavaFX启动过程是通过调用其中一个静态Application.launch(...)
方法或(使用Oracle JDK)启动,方法是启动JVM并指定Application
子类作为主类(即使它没有main
方法)。
然后启动过程:
Application
子类init()
子类上调用Application
(默认实现是无操作)start()
子类上调用Application
,在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);
}
}