0

0

JavaFX 8 全屏缩放应用:解决 BorderPane 重复添加子节点问题

心靈之曲

心靈之曲

发布时间:2025-10-12 12:42:09

|

719人浏览过

|

来源于php中文网

原创

javafx 8 全屏缩放应用:解决 borderpane 重复添加子节点问题

本文旨在解决 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()。

Quillbot
Quillbot

一款AI写作润色工具,QuillBot的人工智能改写工具将提高你的写作能力。

下载

因此,修改后的代码应该如下:

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() {
            @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: 使用 setTop()、setBottom()、setLeft()、setRight() 和 setCenter() 方法来设置子节点的位置,避免直接操作 getChildren() 列表。
  • 避免重复添加: 仔细检查代码,确保没有将同一个节点多次添加到同一个容器中。
  • 理解布局原理: 深入理解 JavaFX 布局容器的工作原理,有助于避免类似错误,并更好地控制应用的界面布局。
  • 全屏缩放实现: 示例代码中已经包含了layoutChildren()方法,通过计算缩放比例,对各个组件进行缩放和居中,实现了基本的全屏缩放功能。

通过遵循这些建议,开发者可以避免 BorderPane 重复添加子节点的问题,并构建出稳定、可靠的 JavaFX 应用。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
console接口是干嘛的
console接口是干嘛的

console接口是一种用于在计算机命令行或浏览器开发工具中输出信息的工具,提供了一种简单的方式来记录和查看应用程序的输出结果和调试信息。本专题为大家提供console接口相关的各种文章、以及下载和课程。

415

2023.08.08

console.log是什么
console.log是什么

console.log 是 javascript 函数,用于在浏览器控制台中输出信息,便于调试和故障排除。想了解更多console.log的相关内容,可以阅读本专题下面的文章。

510

2024.05.29

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

1

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

1

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

0

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

0

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

3

2026.01.29

clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

24

2026.01.29

clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址
clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址

clawdbot龙虾机器人官网入口:https://clawd.bot/,clawdbot ai是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

16

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 7.9万人学习

Java 教程
Java 教程

共578课时 | 53.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号