提问者:小点点

JavaFX:如何使用新值更新边框窗格的中心视图


我正在创建一个程序,顶部有一排按钮,侧面有一排按钮。顶部的按钮控制视图,侧面的按钮控制在视图中引用什么对象。

我的主/根视图是一个边框窗格。

关键是,当我单击这些按钮中的任何一个时,更改我的主控制器中的值,然后使用这些新值重新加载中心视图。我认为编写一个可以更改值的方法,然后根据这些值设置新的中心,这很简单。

但是,当我测试它时,它可以显示我已经要求它显示的两个值,但每当我运行时都会给我大量的红色错误代码。

我的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));
}

}

我做错了什么?


共1个答案

匿名用户

您的应用程序在结构上基本上是错误的:您使用的是应用程序子类作为控制器,这根本不起作用(至少不容易)。您需要使用与控制器不同的启动类(Application的子类)来重构它。实际上,任何完整的示例都可以作为模板,但Oracle教程是一个很好的开始。

正在发生的情况如下:

当您在< code>MainViewController.main(...),启动FX工具包,创建应用程序类< code>MainViewController的实例,启动FX应用程序线程,并在FX应用程序线程上调用属于< code>MainViewController实例的< code>start()方法。

当您调用 FXMLLoaderload() 方法时,它会在指定位置分析 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的设计意图。