如何创建完全定制的JavaFX控件?或者:如何创建具有动态绘制背景的窗格?

如何创建完全定制的JavaFX控件?或者:如何创建具有动态绘制背景的窗格?,java,swing,javafx,Java,Swing,Javafx,我想创建完全定制的JavaFX控件。我不想“更喜欢作曲”,因为我没有东西可以作曲 例如,假设我需要一个窗格,其中包含坐标网格。窗格应与普通窗格一样工作,即可以在此处添加控件或几何图形,但应在窗格的背景处绘制网格。此外,应在窗格边缘绘制数值 所有这些都应该动态地反映窗格的变换和视口 另一个例子:假设我想将平铺图像作为背景。有数以百万计的磁贴,就像谷歌地图一样,所以我不能将它们作为子节点加载,因为它们会耗尽内存。我需要在用户滚动窗格时动态加载和卸载它们 同样,窗格的行为应与普通窗格相同,即可以向其中

我想创建完全定制的JavaFX控件。我不想“更喜欢作曲”,因为我没有东西可以作曲

例如,假设我需要一个窗格,其中包含坐标网格。窗格应与普通窗格一样工作,即可以在此处添加控件或几何图形,但应在窗格的背景处绘制网格。此外,应在窗格边缘绘制数值

所有这些都应该动态地反映窗格的变换和视口

另一个例子:假设我想将平铺图像作为背景。有数以百万计的磁贴,就像谷歌地图一样,所以我不能将它们作为子节点加载,因为它们会耗尽内存。我需要在用户滚动窗格时动态加载和卸载它们

同样,窗格的行为应与普通窗格相同,即可以向其中添加child

如何做到这一点?我发现,类似于
paintConponent
的低级方法要么不存在,要么被弃用。那么,该怎么办

更新

我想设计一个具有自定义背景的容器

例如,像这样:

(它应该是无止境的,即控件调整大小后显示更多行)

默认情况下,容器不应有子容器,但仍有背景。背景不应是容器的子级。一、 程序员应该能够将子项添加到此容器中,并且只有在这之后,子项才会出现在容器中。它们应该出现在背景之上

像这样:

注意,我们这里只有两个孩子

更新

在下面的代码中,将显示滚动条标准控件。正如你们所看到的,它包含可以移动的旋钮和可以按下的箭头按钮

同时,该对照组中的儿童人数报告为零

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class ChildrenOfDefaultControls extends Application {
   @Override
   public void start(Stage primaryStage) throws Exception

   {

      ScrollBar scrollBar = new ScrollBar();

      AnchorPane root = new AnchorPane(scrollBar);
      AnchorPane.setLeftAnchor(scrollBar, 0.);
      AnchorPane.setRightAnchor(scrollBar, 0.);
      AnchorPane.setTopAnchor(scrollBar, 100.);

      Scene scene = new Scene(root, 800, 600);

      primaryStage.setTitle(String.valueOf(scrollBar.getChildrenUnmodifiable().size()));
      primaryStage.setScene(scene);
      primaryStage.show();

   }

   public static void main(String[] args) {
      Application.launch(ChildrenOfDefaultControls.class, args);
   }
}
好吧,我同意如果每个人都说不可能像挥杆一样画画,那我们来作曲吧。但是,如何向用户隐藏此合成,就像它那样
滚动条
控件?

使用用户提供的命令呈现任意内容;将
画布
添加到具有适当布局的
窗格
。在此情况下,“
CanvasPane
Canvas
的实例包装在
窗格中,并覆盖
layoutChildren()
,使画布尺寸与封闭的
窗格相匹配。”将
root
BorderPane
切换到
StackPane
可以在动画背景上放置控件。该示例添加了一个
复选框
,但您可以添加一个包含任何所需控件的
父项
。调整舞台大小以查看效果

    StackPane root = new StackPane();
    root.getChildren().addAll(canvasPane, cb);

附录:在@jewelsea编写的这篇相关文章中,背景直接在
layoutChildren()
的实现中呈现,并在调整封闭的
父项的大小时填充
窗格

你还是个孩子的时候还拥有
Canvas

是的,这是渲染无限背景的一种方便方法,尽管有一些开销:“每次调用都会将必要的参数推送到缓冲区,然后在脉冲结束时,渲染线程会将这些参数渲染到
画布
节点的图像上。”

我想像Oracle那样从头开始设计控件,而不是将现有控件组合起来

如前所述,“JavaFXUI控件……是使用场景图中的节点构建的”,包括图像、文本和文本。这大大减少了Swing
paintComponent()
甚至JavaFX
getGraphicsContext2D()
所需的上下文切换开销。当然,正如前面所讨论的,“编写新的UI控件并不是一件小事。”您将不得不决定在您的用例中,这项工作是否合理

我是否可以对控件用户隐藏部分子控件,以便他不会看到控件包含
画布

是的,
Canvas
很方便,但不是必需的。在下面的示例中,
LinePane扩展了StackPane
,并用问题中的一部分图像平铺一个
矩形。请注意,
LinePane
LineTest
中仍然是一个
StackPane
,它在
Pos.TOP\u LEFT
中添加了一个
按钮。默认情况下,
矩形
占据
位置中心
。重写
layoutChildren()
可以动态调整
矩形的大小

使用提供的命令呈现任意内容;将
画布
添加到具有适当布局的
窗格
。在此情况下,“
CanvasPane
Canvas
的实例包装在
窗格中,并覆盖
layoutChildren()
,使画布尺寸与封闭的
窗格相匹配。”将
root
BorderPane
切换到
StackPane
可以在动画背景上放置控件。该示例添加了一个
复选框
,但您可以添加一个包含任何所需控件的
父项
。调整舞台大小以查看效果

    StackPane root = new StackPane();
    root.getChildren().addAll(canvasPane, cb);

附录:在@jewelsea编写的这篇相关文章中,背景直接在
layoutChildren()
的实现中呈现,并在调整封闭的
父项的大小时填充
窗格

你还是个孩子的时候还拥有
Canvas

是的,这是渲染无限背景的一种方便方法,尽管有一些开销:“每次调用都会将必要的参数推送到缓冲区,然后在脉冲结束时,渲染线程会将这些参数渲染到
画布
节点的图像上。”

我想像Oracle那样从头开始设计控件,而不是将现有控件组合起来

如前所述,“JavaFXUI控件……是使用nod构建的