如何创建完全自定义的JavaFX控件? 或者:如何使用动态绘制的背景创建窗格?
我想创建完全自定义的JavaFX控件。 我不想“喜欢作曲”,因为我没有东西可以写作。
例如,假设我需要一个窗格,里面有坐标网格。 窗格应该像普通窗格一样工作,即应该可以在那里添加控件或几何图形,但是在窗格的背景中应该绘制网格。 另外,应在窗格的边缘绘制数值。
所有这些都应该动态地反映窗格的转换和视口。
另一个例子:假设我想将平铺图像作为beckground。 有数百万的瓷砖,比如谷歌地图,所以我无法将它们作为子节点加载,因为它们会耗尽内存。 当用户滚动窗格时,我需要动态加载和卸载它们。
同样,窗格应该像普通窗格一样运行,即可以向其添加子项。
怎么做到这一点? 我发现,类似于paintConponent
的低级方法要么不存在,要么弃用。 那么该怎么办?
UPDATE
我想设计一个具有自定义背景的容器。
例如,像这样:
(它应该是无穷无尽的,即一旦控件resize就会显示更多行)
容器默认情况下应该没有子节点,但仍然具有背景。 背景不应该是容器的子代。 我,程序员,应该能够将子容器添加到此容器中,只有在此之后,子容器才会出现在容器中。 它们应该出现在背景之上。
像这样:
请注意,我们这里只有2个孩子。
UPDATE
在下面的代码中,显示ScrollBar
标准控件。 如您所见,它包含可以移动的旋钮和可以按下的箭头按钮。
同时,此控件中的子项数报告为零。
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); } }
好吧,我同意如果每个人都说不可能像在Swing中那样画画,那就让我们来做作曲。 但是如何从用户那里隐藏这个组合,因为它完成了ScrollBar
控件?
使用Canvas
使用GraphicsContext
提供的命令呈现任意内容; 将Canvas
添加到具有合适布局的Pane
中。 在此示例中 ,“ CanvasPane
在Pane
包装Canvas
实例并覆盖layoutChildren()
以使canvas尺寸与封闭Pane
匹配。” 将root
从BorderPane
切换到StackPane
允许将控件放在动画背景的顶部。 该示例添加了一个CheckBox
,但您可以添加包含任何所需控件的Parent
。 调整舞台大小以查看效果。
StackPane root = new StackPane(); root.getChildren().addAll(canvasPane, cb);
附录:在@jewelsea 引用的这个相关示例中 ,背景直接在layoutChildren()
的实现中呈现,同时在调整封闭Parent
的大小时填充Pane
。
你小时候还有
Canvas
。
是的,这是渲染无尽背景的一种方便方法,虽然有一些开销:“每次调用都会将必要的参数推送到缓冲区,然后在脉冲结束时渲染线程将它们渲染到Canvas
节点的图像上。 “
我想从头开始设计像Oracle一样的控件,而不是现有的控件。
如此处所讨论的,“JavaFX UI控件……是通过使用场景图中的节点构建的”,包括图像,文本和基本几何形状 。 这显着减轻了Swing paintComponent()
甚至JavaFX getGraphicsContext2D()
所需的上下文切换的开销。 当然,正如这里所讨论的,“编写新的UI控件并非易事。” 您必须确定您的用例中的工作是否合理。
我可以隐藏部分孩子来自控制用户,这样他就不会看到该控件包含
Canvas
吗?
是的, Canvas
很方便,但不是必需的。 在下面的示例中, LinePane extends StackPane
并在您的问题中使用图像的一部分来LinePane extends StackPane
Rectangle
。 请注意, LinePane
仍然是LinePane
中的StackPane
,它在LineTest
中添加了一个Button
。 默认情况下, Rectangle
占用Pos.CENTER
。 覆盖layoutChildren()
可以动态调整Rectangle
大小。
import javafx.application.Application; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.image.Image; import javafx.scene.layout.StackPane; import javafx.scene.paint.ImagePattern; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; /** * @see https://stackoverflow.com/a/43814198/230513 */ public class LineTest extends Application { @Override public void start(Stage Stage) { Stage.setTitle("LineTest"); LinePane linePane = new LinePane(); Button button = new Button("Button"); LinePane.setAlignment(button, Pos.TOP_LEFT); LinePane.setMargin(button, new Insets(50)); linePane.getChildren().add(button); Scene scene = new Scene(linePane, 320, 240); Stage.setScene(scene); Stage.show(); } private static class LinePane extends StackPane { private static final String URL = "https://i.stack.imgur.com/bqXKK.png"; private final Image lines = new Image(URL); private final Rectangle rectangle = new Rectangle(); public LinePane() { rectangle.setFill(new ImagePattern(lines, 8, 22, 34, 34, false)); getChildren().add(rectangle); } @Override protected void layoutChildren() { super.layoutChildren(); final double x = snappedLeftInset(); final double y = snappedTopInset(); final double w = snapSize(getWidth()) - x - snappedRightInset(); final double h = snapSize(getHeight()) - y - snappedBottomInset(); rectangle.setLayoutX(x); rectangle.setLayoutY(y); rectangle.setWidth(w); rectangle.setHeight(h); } } public static void main(String[] args) { launch(args); } }
- 是否有可能仅从一个特定分支触发Jenkins?
- validation具有基于树的结构的文件
- XIncludeAwareParserConfiguration与XMLParserConfiguration不兼容
- 一段时间后,随着ProcessBuilder阻止了Java应用程序
- 为什么我的Geb测试返回“无法从回调中创建驱动程序”,即使在Grails中更新我的Selenium依赖项后?
- 为Eclipse设置正确的PATH
- MongoDB $ aggregate $ push Java Spring Data中的多个字段
- Quartz – 在一周和几天的某一天每两周安排一次工作
- 如何在java中将XML转换为JSON?