
本文旨在解决 JavaFX 8 应用中实现全屏缩放时遇到的 `BorderPane` 重复添加子节点的问题。通过分析错误原因和提供正确的代码示例,帮助开发者避免类似错误,并实现期望的全屏缩放效果。文章重点在于理清 `BorderPane` 的使用方式,并提供清晰的布局策略。
在 JavaFX 应用开发中,实现全屏缩放功能是常见的需求。然而,在实现过程中,开发者可能会遇到各种问题,例如 BorderPane 重复添加子节点导致的异常。本文将针对这一问题进行详细分析,并提供解决方案。
错误信息 duplicate children added: parent = BorderPane 表明,在代码中,inputBar 被重复添加到了 root (一个 BorderPane 实例) 中。查看代码:
this.root = new BorderPane();
// . . .
root.getChildren().addAll(
console,
scroll,
inputBar
);
root.setBottom(inputBar);inputBar 首先通过 root.getChildren().addAll() 添加到 BorderPane 中,然后又通过 root.setBottom(inputBar) 添加到 BorderPane 的底部区域。这导致了重复添加,从而引发异常。
立即学习“Java免费学习笔记(深入)”;
BorderPane 是一种布局容器,它将子节点放置在五个区域:顶部 (Top)、底部 (Bottom)、左侧 (Left)、右侧 (Right) 和中心 (Center)。正确使用 BorderPane 的方式是使用其提供的 setTop()、setBottom()、setLeft()、setRight() 和 setCenter() 方法来设置子节点的位置,而不是直接使用 getChildren().addAll()。
因此,修改后的代码应该如下:
this.root = new BorderPane(); root.setCenter(scroll); // 将 scroll 放在中心区域 root.setBottom(inputBar); // 将 inputBar 放在底部区域
在这个修改后的代码中,console 被放置在 ScrollPane 中,而 scroll 被放置在 BorderPane 的中心区域。inputBar 被放置在 BorderPane 的底部区域。这样就避免了重复添加子节点的问题。
下面是修改后的 Console 类的代码示例:
package application.console;
import java.util.List;
import application.areas.startingArea.SA;
import application.areas.vanguardForest.VFCmds;
import application.areas.vanguardForest.VFNavi;
import application.areas.vanguardForest.VFPkups;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
public class Console extends Region {
public static double WIDTH = 990;
public static double HEIGHT = 525;
private final Font cinzel;
private final BorderPane root;
private final VBox console;
private final ScrollPane scroll;
private final HBox inputBar;
private final TextField input;
private final Text carrot;
public Console() {
this.root = new BorderPane();
root.setStyle("-fx-background-color: #232323;");
this.cinzel = Font.loadFont("file:fonts/static/Cinzel-Medium.ttf", 16);
this.console = new VBox();
console.setPrefWidth(WIDTH);
console.setPrefHeight(HEIGHT);
this.scroll = new ScrollPane();
scroll.setContent(console);
scroll.setStyle("-fx-background: #232323;"
+ "-fx-background-color: transparent;"
+ "-fx-border-color: #232323;"
+ "-fx-focus-color: #232323;");
scroll.setHbarPolicy(ScrollBarPolicy.NEVER);
scroll.setVbarPolicy(ScrollBarPolicy.NEVER);
scroll.setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, null, null)));
console.setStyle("-fx-background-color: #232323;"
+ "-fx-focus-color: #232323;");
console.heightProperty().addListener(new ChangeListener<Object>() {
@Override
public void changed(ObservableValue<?> observable, Object oldValue, Object newValue) {
scroll.setVvalue((Double)newValue);
}
});
this.inputBar = new HBox();
inputBar.setPrefSize(WIDTH, 16);
this.input = new TextField();
input.setStyle("-fx-background-color: transparent;"
+ "-fx-text-fill: #FFFFFF;"
+ "-fx-highlight-fill: #FFFFFF;"
+ "-fx-highlight-text-fill: #232323;"
);
input.setFont(cinzel);
input.setPrefWidth(WIDTH);
this.carrot = new Text(" > ");
carrot.setFont(Font.loadFont("file:fonts/static/Cinzel-Medium.ttf", 24));
carrot.setFill(Color.WHITE);
inputBar.getChildren().addAll(carrot, input);
root.setMinSize(WIDTH, (HEIGHT - input.getHeight()));
input.setOnAction(e -> {
String s = (input.getText()).stripTrailing();
if ((SA.isBuried || SA.inVF) && SS.gameStart) {
Cmds.commands(s); //has general functions
VFCmds.commands(s); //doesn't have function until specific command
VFPkups.pickUp(s); //commands that allows pickups to be made within the game
VFNavi.commands(s); //commands navigation for selected area
} else {
Cmds.commands(s);
}
input.clear();
});
// root.getChildren().addAll(console, scroll, inputBar); // Removed this line
root.setCenter(scroll); // Added this line
root.setBottom(inputBar); // Added this line
}
@Override
protected void layoutChildren() {
double xScale = getWidth() / root.getWidth();
double yScale = getHeight() / root.getHeight();
double scale = Math.min(xScale, yScale);
for (BorderPane bp : List.of(root)) {
scaleAndCenter(bp, scale);
}
for (VBox vb : List.of(console)) {
scaleAndCenter(vb, scale);
}
for (HBox hb : List.of(inputBar)) {
scaleAndCenter(hb, scale);
}
for (ScrollPane sp : List.of(scroll)) {
scaleAndCenter(sp, scale);
}
for (TextField tf : List.of(input)) {
scaleAndCenter(tf, scale);
}
for (Text text : List.of(carrot)) {
scaleAndCenter(text, scale);
}
}
private void scaleAndCenter(BorderPane root, double scale) {
double w = scale * root.getWidth();
double h = scale * root.getHeight();
root.setPrefSize(w, h);
root.relocate((getWidth() - w) / 2, (getHeight() - h) / 2);
}
private void scaleAndCenter(VBox vb, double scale) {
double w = scale * vb.getWidth();
double h = scale * vb.getHeight();
vb.setPrefSize(w, h);
vb.relocate((getWidth() - w) / 2, (getHeight() - h) / 2);
}
private void scaleAndCenter(HBox hb, double scale) {
double w = scale * hb.getWidth();
double h = scale * hb.getHeight();
hb.setPrefSize(w, h);
hb.relocate((getWidth() - w) / 2, (getHeight() - h) / 2);
}
private void scaleAndCenter(TextField input, double scale) {
double w = scale * input.getWidth();
double h = scale * input.getHeight();
input.setPrefSize(w, 16);
input.relocate((getWidth() - w) / 2, (getHeight() - h) / 2);
}
private void scaleAndCenter(ScrollPane scroll, double scale) {
double w = scale * scroll.getWidth();
double h = scale * scroll.getHeight();
scroll.setPrefSize(w, h);
scroll.relocate((getWidth() - w) / 2, (getHeight() - h) / 2);
}
private void scaleAndCenter(Text text, double scale) {
double w = scale * text.getLayoutBounds().getWidth();
double h = scale * text.getLayoutBounds().getHeight();
double size = scale * text.getFont().getSize();
text.setFont(Font.font(
text.getFont().getFamily(),
size));
text.relocate((getWidth() - w) / 2, (getHeight() - h) / 2);
}
}通过遵循这些建议,开发者可以避免 BorderPane 重复添加子节点的问题,并构建出稳定、可靠的 JavaFX 应用。
以上就是JavaFX 8 全屏缩放应用:解决 BorderPane 重复添加子节点问题的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号