我正在创建一个程序,顶部有一排按钮,侧面有一排按钮。顶部的按钮控制视图,侧面的按钮控制在视图中引用什么对象。
我的主/根视图是一个边框窗格。
关键是,当我单击这些按钮中的任何一个时,更改我的主控制器中的值,然后使用这些新值重新加载中心视图。我认为编写一个可以更改值的方法,然后根据这些值设置新的中心,这很简单。
但是,当我测试它时,它可以显示我已经要求它显示的两个值,但每当我运行时都会给我大量的红色错误代码。
我的MainViewController如下所示:
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class MainViewController extends Application {
@FXML
private Button cabin1;
@FXML
private Button cabin2;
@FXML
private Button tab1;
@FXML
private Button tab2;
@FXML
public void setCabinOne() throws IOException {
cabinIndex=1;
setCenterView();
}
@FXML
public void setCabinTwo() throws IOException {
cabinIndex=2;
setCenterView();
}
@FXML
public void setTabOne() throws IOException {
tabIndex=1;
setCenterView();
}
@FXML
public void setTabTwo() throws IOException {
tabIndex=2;
setCenterView();
}
public int getCabinIndex() {
return cabinIndex;
}
public int getTabIndex() {
return tabIndex;
}
private int tabIndex=0;
private int cabinIndex=1;
public Stage primaryStage;
private BorderPane mainPane;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage=primaryStage;
primaryStage.setTitle("Test");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainViewController.class.getResource("MainView.fxml"));
mainPane = loader.load();
setCenterView();
Scene scene = new Scene(mainPane);
primaryStage.setScene(scene);
primaryStage.show();
}
public void setCenterView() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainViewController.class.getResource("TestView.fxml"));
AnchorPane testPane = loader.load();
TestViewController tvc = loader.<TestViewController>getController();
tvc.changeLabel(getCabinIndex());
tvc.changeIndex(getTabIndex());
mainPane.setCenter(testPane);
}
}
我的TestViewController如下所示:
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class TestViewController {
@FXML
private Label cabinIndex;
@FXML
private Label tabIndex;
public void initialise() {
this.changeLabel(0);
this.changeIndex(0);
}
public void changeLabel(int n) {
cabinIndex.setText("Cabin "+Integer.toString(n));
}
public void changeIndex(int n) {
tabIndex.setText("Tab "+Integer.toString(n));
}
}
我做错了什么?
您的应用程序在结构上基本上是错误的:您使用的是应用程序子类作为控制器,这根本不起作用(至少不容易)。您需要使用与控制器不同的启动类(Application
的子类)来重构它。实际上,任何完整的示例都可以作为模板,但Oracle教程是一个很好的开始。
正在发生的情况如下:
当您在< code>MainViewController.main(...),启动FX工具包,创建应用程序类< code>MainViewController的实例,启动FX应用程序线程,并在FX应用程序线程上调用属于< code>MainViewController实例的< code>start()方法。
当您调用 FXMLLoader
的 load()
方法时,它会在指定位置分析 FXML 文件。当它看到 fx:controller
属性(我假设是 fx:controller=“MainViewController”)
时,它会创建指定控制器类的实例。解析 FXML 后,将使用 FXML 文件中的相应对象初始化任何匹配的@FXML
注释字段(属于该实例),然后在该实例上调用 initialize()
方法。
所以请注意,现在您实际上有两个MainViewController
实例:一个是调用FXMLLoader.load()
的实例,另一个是由FXMLLoader
创建的实例。由FXMLLoader
创建的实例中的@FXML
注释字段已初始化,但原始实例中的字段仍设置为默认值null
。相反,mainPane
字段在原始MainViewController
实例中的start
方法中初始化,但从未在FXMLLoader
创建的实例中初始化。因此,当您按下按钮并调用setCenterView()
(我假设这是FXML的设置方式)时,当mainPane
仍然null
时,您将调用mainPane.setCenter()
。
你可以强迫它像这样工作。类似于:从MainView.fxml中移除< code>fx:controller属性,并调用< code > loader . set controller(this)。但是当你偏离一个框架通常使用的模式那么远时,你的代码就变得很难维护和调试。我建议遵循API的设计意图。