You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX自定义布局组件虚拟节点子元素渲染异常求助

JavaFX自定义虚拟化布局容器子元素渲染失效问题

渲染大量JavaFX节点时,数量达到一定规模后滚动会明显卡顿,因此打算实现类似TableView的虚拟化方案,但由于存在复杂布局需求(部分节点需并排显示、部分需独占一行),TableView无法满足需求。

自行实现自定义布局组件后,出现子元素布局失效的问题:滚动时仅能看到BorderPane的浅红色背景,其内部Label的背景与文本完全无法渲染。

修改createRealNode方法为以下实现时,Label可正常显示,但业务场景需要使用BorderPane、StackPane、GridPane等布局容器来承载复杂子节点结构。

原实现代码

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class VirtualNodesDemo extends Application {
    @Override
    public void start(Stage primaryStage) {
        int virtualNodes = 100;
        double nodeWidth = 100;
        double nodeHeight = 100;

        StackPane root = new StackPane();

        Pane content = new Pane() {
            @Override
            protected void layoutChildren() {
                System.out.println("content.layoutChildren() ...");

                getChildren().clear();

                ScrollPane scrollPane = (ScrollPane) getParent().getParent().getParent();

                double viewportHeight = scrollPane.getViewportBounds().getHeight();
                double scrollTop = scrollPane.getVvalue() * (getPrefHeight() - viewportHeight);

                double y = 0;

                for (int i = 0; i < virtualNodes; i++) {
                    if (y + nodeHeight > scrollTop && y < scrollTop + viewportHeight) {
                        Pane pane = createRealNode(i);
                        pane.resizeRelocate(10, y, nodeWidth, nodeHeight);
                        pane.layout();
                        getChildren().add(pane);
                    } else {
                        break;
                    }
                    y += nodeHeight + 10;
                }

                setPrefHeight(y);
            }

            private Pane createRealNode(int i) {
                BorderPane borderPane = new BorderPane();
                borderPane.setManaged(false);
                Label label = new Label("Node " + i);
                label.setStyle("-fx-background-color: #aaf;");
                borderPane.setCenter(label);
                borderPane.setStyle("-fx-background-color: #faa;");
                return borderPane;
            }
        };

        ScrollPane scrollPane = new ScrollPane(content);
        scrollPane.setFitToWidth(true);
        scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
        scrollPane.vvalueProperty().addListener(observable -> content.layout());
        root.getChildren().add(scrollPane);

        Scene scene = new Scene(root, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

修改后可正常显示的createRealNode方法

private Pane createRealNode(int i) {
    Label label = new Label("Node " + i);
    label.setStyle("-fx-background-color: #aaf;");
    Pane p = new Pane();
    p.setManaged(false);
    p.getChildren().add(label);
    return p;
}

内容的提问来源于stack exchange,提问作者user3151902

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 22:48:23