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
相关产品推荐
相关产品推荐

