JavaFX:如何使用新值更新边框的中心视图 [英] JavaFX: How to update the center view of a borderpane with new values

查看:58
本文介绍了JavaFX:如何使用新值更新边框的中心视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

关键是,当我单击这些按钮中的任何一个时,要在MainController中更改一个值,然后使用这些新值重新加载中心视图.我以为写一个可以更改该值然后根据这些值设置新中心的方法是如此简单.

但是,在我对其进行测试时,它可以显示我已经要求它显示的两个值,但是每次运行时都会给我带来大量红色错误代码.

我的MainViewController如下所示:

  import java.io.IOException;导入javafx.application.Application;导入javafx.fxml.FXML;导入javafx.fxml.FXMLLoader;导入javafx.scene.Scene;导入javafx.scene.control.Button;导入javafx.scene.layout.AnchorPane;导入javafx.scene.layout.BorderPane;导入javafx.stage.Stage;公共类MainViewController扩展了Application {@FXML私人按钮小屋1;@FXML私人按钮小屋2;@FXML私人按钮tab1;@FXML私人Button tab2;@FXML公共无效setCabinOne()引发IOException {CabinIndex = 1;setCenterView();}@FXML公共无效setCabinTwo()引发IOException {cabIndex = 2;setCenterView();}@FXML公共无效setTabOne()引发IOException {tabIndex = 1;setCenterView();}@FXML公共无效setTabTwo()引发IOException {tabIndex = 2;setCenterView();}public int getCabinIndex(){返回cabIndex;}public int getTabIndex(){返回tabIndex;}private int tabIndex = 0;私人int CabinIndex = 1;公共舞台主舞台;私有BorderPane mainPane;公共静态void main(String [] args){发射(参数);}@Overridepublic void start(Stage primaryStage)引发异常{this.primaryStage = primaryStage;primaryStage.setTitle("Test");FXMLLoader loader =新的FXMLLoader();loader.setLocation(MainViewController.class.getResource("MainView.fxml"));mainPane = loader.load();setCenterView();场景场景=新场景(mainPane);primaryStage.setScene(scene);primaryStage.show();}公共无效setCenterView()引发IOException {FXMLLoader loader =新的FXMLLoader();loader.setLocation(MainViewController.class.getResource("TestView.fxml"));AnchorPane testPane = loader.load();< TestViewController> getController();.tvc.changeLabel(getCabinIndex());tvc.changeIndex(getTabIndex());mainPane.setCenter(testPane);}} 

和我的TestViewController如下所示:

  import javafx.fxml.FXML;导入javafx.scene.control.Label;公共类TestViewController {@FXML私人标签cabIndex;@FXML私人标签tabIndex;公共无效的initialize(){this.changeLabel(0);this.changeIndex(0);}公共无效changeLabel(int n){cabIndex.setText("Cabin" + Integer.toString(n));}公共无效的changeIndex(int n){tabIndex.setText("Tab" + Integer.toString(n));}} 

我在做什么错了?

解决方案

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

正在发生的事情如下:

当您在 MainViewController.main(...)中调用 Application.launch()时,将启动FX工具包,这是您的应用程序类的实例创建MainViewController ,启动FX Application线程,并在FX Application Thread上调用属于 MainViewController 实例的 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 .

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

I am creating a program which has a row of buttons on the top, and a row of buttons on the side. The top buttons control the view, and the side buttons control what object to reference in the view.

My main/root view is a borderpane.

The point is to, as I click on any of these buttons, to change a value in my MainController, and then reload the center view with these new values. I thought it would be so simple as to write a method that would change the value and then set a new center according to these values.

However, as I test it, it can display the two values I have already asked it to display, but gives me a huge load of red error code whenever I run.

My MainViewController looks as follows:

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

}

and my TestViewController looks as follows:

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

}

What am I doing wrong?

解决方案

Your application is basically structurally wrong: you are using the application subclass as the controller, and this simply won't work (at least, not easily). You need to refactor this with a startup class (subclass of Application) that is distinct from the controller. Virtually any complete example will work as a template for you, but the Oracle tutorial is a good place to start.

What is happening is as follows:

When you call Application.launch() in MainViewController.main(...), the FX toolkit is started, an instance of your application class MainViewController is created, the FX Application Thread is started, and the start() method belonging to the MainViewController instance is invoked on the FX Application Thread.

When you call the FXMLLoader's load() method, it parses the FXML file at the specified location. When it sees the fx:controller attribute, which I'm assuming is fx:controller="MainViewController", it creates an instance of the specified controller class. Once the FXML is parsed, any matching @FXML-annotated fields (belonging to that instance) are initialized with the corresponding objects from the FXML file, and then the initialize() method is called on that instance.

So notice now you actually have two instances of MainViewController: the one from which FXMLLoader.load() was called, and the one created by the FXMLLoader. The @FXML-annotated fields in the instance created by the FXMLLoader are initialized, but the ones in the original instance remain set to the default value of null. Conversely, the mainPane field is initialized in the start method in the original MainViewController instance, but is never initialized in the instance created by the FXMLLoader. So when you press the button and invoke setCenterView() (I assume this is how your FXML is set up), you end up calling mainPane.setCenter() when mainPane is still null.

You could probably just about force it to work like this. Something like: remove the fx:controller attribute from MainView.fxml, and call loader.setController(this). But when you stray that far from the usual patterns used by a framework, your code becomes hard to maintain and debug. I would recommend following the design intended by the API.

这篇关于JavaFX:如何使用新值更新边框的中心视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆