0

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

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

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

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

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

}

我究竟做错了什么?

4

1 回答 1

1

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

发生的事情如下:

当您调用Application.launch()MainViewController.main(...),FX 工具包被启动,您的应用程序类的一个实例MainViewController被创建,FX 应用程序线程被启动,并且start()属于该MainViewController实例的方法被在 FX 应用程序线程上被调用。

当您调用FXMLLoader'load()方法时,它会在指定位置解析 FXML 文件。当它看到fx:controller我假设的属性时fx:controller="MainViewController",它会创建指定控制器类的实例。一旦解析了 FXML,任何匹配的带注释的@FXML字段(属于该实例)都会使用 FXML 文件中的相应对象进行初始化,然后initialize()在该实例上调用该方法。

所以注意现在你实际上有两个实例MainViewController:一个FXMLLoader.load()被调用,一个由FXMLLoader. 由创建的实例中的@FXML-annotated 字段FXMLLoader已初始化,但原始实例中的字段仍设置为 的默认值null。相反,该mainPane字段start在原始MainViewController实例中的方法中被初始化,但从未在由FXMLLoader. 因此,当您按下按钮并调用时setCenterView()(我假设这就是您的 FXML 的设置方式),您最终会调用mainPane.setCenter()when mainPaneis still null

你可能只是强迫它像这样工作。类似于:fx:controller从 MainView.fxml 中删除属性,然后调用loader.setController(this). 但是,当您偏离框架使用的通常模式时,您的代码将变得难以维护和调试。我建议遵循 API 预期的设计。

于 2014-10-17T01:29:41.883 回答