java 嵌套对象转xml,将嵌套对象从fxml映射到对象

I created the following object which should be responsible for displaying a steeringwheel in my win app.

@DefaultProperty("children")

public class SteeringWheel extends Region {

@FXML

private Circle backgroundCircle;

@FXML

private Circle innerCircle;

@FXML

private Label mylabel;

public ObservableList getChildren() {

return super.getChildren();

}

public void setCirclesLocations() {

double centerPointX = getWidth() / 2;

double centerPointY = getHeight() / 2;

setCircleLocation(backgroundCircle, centerPointX, centerPointY);

setCircleLocation(innerCircle, centerPointX, centerPointY);

}

private void setCircleLocation(Circle c, double x, double y) {

c.setCenterX(x);

c.setCenterY(y);

}

and my fxml file contains the following decleration :

.....

I'm trying to map the xml initialization to this object but it doesn't work. In my main I'm trying to run the setCircleLocations but I'm getting nullpointer exception.

FXMLLoader fxl=new FXMLLoader();

try {

BorderPane root = fxl.load(getClass().getResource("Window.fxml").openStream());

WindowController wc=fxl.getController(); // View

Scene scene = new Scene(root,400,400);

scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());

primaryStage.setScene(scene);

primaryStage.show();

wc.steeringWheel.setCirclesLocations();

} catch (IOException e) {

e.printStackTrace();

}

my window controller :

public class WindowController {

@FXML

SteeringWheel steeringWheel;

}

in addition, in the xml file I'm getting the following error for the children of the SteeringWheel : Unresolved fx:id reference

stack trace :

Exception in Application start method

java.lang.reflect.InvocationTargetException

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.base/java.lang.reflect.Method.invoke(Method.java:566)

at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:473)

at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:372)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.base/java.lang.reflect.Method.invoke(Method.java:566)

at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)

Caused by: java.lang.RuntimeException: Exception in Application start method

at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:973)

at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:198)

at java.base/java.lang.Thread.run(Thread.java:834)

Caused by: java.lang.NullPointerException

at view.WheelingSteer.setCircleLocation(WheelingSteer.java:36)

at view.WheelingSteer.setCirclesLocations(WheelingSteer.java:31)

at view.Main.start(Main.java:33)

at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:919)

at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)

at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)

at java.base/java.security.AccessController.doPrivileged(Native Method)

at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)

at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)

at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)

at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)

... 1 more

Exception running application view.Main

解决方案

Only the controller has the appropriate fields injected. Your SteeringWheel class is not a controller, thus those @FXML annotated fields are not injected. The objects you intend to be injected into those fields are put in the children list, though, so you could access them there. However, it appears you want SteeringWheel to be its own component, where the two Circles and Label are always present, regardless of how the SteeringWheel is used, so it doesn't make sense to try and define the children in a separate location.

Since you are extending Region you may want to consider using fx:root:

import java.io.IOException;

import java.io.UncheckedIOException;

import javafx.fxml.FXML;

import javafx.fxml.FXMLLoader;

import javafx.geometry.HPos;

import javafx.geometry.VPos;

import javafx.scene.control.Label;

import javafx.scene.layout.Pane;

import javafx.scene.shape.Circle;

public class SteeringWheel extends Pane {

@FXML private Label myLabel;

@FXML private Circle innerCircle;

@FXML private Circle backgroundCircle;

public SteeringWheel() {

FXMLLoader loader = new FXMLLoader(/* location */);

loader.setRoot(this);

loader.setController(this);

try {

loader.load();

} catch (IOException ex) {

throw new UncheckedIOException(ex);

}

}

@FXML

private void initialize() {

// perform any initialization, if needed

}

@Override

public void layoutChildren() {

// Note: I didn't implement checking if the nodes are managed

// before laying them out. You may wish to add that

// behavior.

// The following will always keep the Circles in the center

// of the Pane. However, it does this by setting the layout[X|Y]

// properties rather than the center[X|Y] properties (as you're

// doing).

double x = snappedLeftInset();

double y = snappedTopInset();

double w = getWidth() - snappedRightInset() - x;

double h = getHeight() - snappedBottomInset() - y;

positionInArea(innerCircle, x, y, w, h, -1, HPos.CENTER, VPos.CENTER);

positionInArea(backgroundCircle, x, y, w, h, -1, HPos.CENTER, VPos.CENTER);

// Layout the Label in the top-left corner

layoutInArea(myLabel, x, y, w, h, -1, HPos.LEFT, VPos.TOP);

}

}

xmlns:fx="http://javafx.com/fxml/1">

Note: I extended Pane instead of Region. The former already extends the latter and already makes the changes you made (i.e. makes the #getChildren() method public and adds a @DefaultProperty("children") annotation).

Note: I overrode #layoutChildren() so that your circles remain in the center no matter what dimensions the parent ends up with. However, it may be easier to simply wrap them in some other layout, such as a StackPane.

Then you would just use SteeringWheel in your other FXML file:

.....

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值