scene graph

一张呈现为树结构的数据结构,java fx 的渲染系统 是通过该数据结构来完成图形的渲染。

所有在树结构的每一个节点称为一个node

根节点(root)是唯一一个没有父母节点的node

没有子节点的node的称为leaf node(叶子节点)

1 . 在scene graph中的每一个node,都有自己的笛卡尔坐标系

Paste_Image.png

2 . 每个node 的视图“呈现”除了几何图形外,其实还包括effect(特效),clip(裁剪),transformation(变换)等特性

3 . Fx 针对每个node 对所包含的特性,提供了不同bound框来囊括这些特性,不同bound的范围

layoutBounds : node geometry

boundsInLocal: node geometry + effects + clip

boundsInParent: node geometry + effects + clip + transformations

Paste_Image.png

public class BoundTest extends Application {

public static void main(String[] args) {

Application.launch(args);

}

@Override

public void start(Stage primaryStage) throws Exception {

VBox root = new VBox();

Scene scene = new Scene(root);

primaryStage.setScene(scene);

// 1. only a simple button

System.out.println("only a simple button");

Button button1 = new Button();

System.out.println("button1=" + button1.getLayoutBounds());

System.out.println("button1=" + button1.getBoundsInLocal());

System.out.println("button1=" + button1.getBoundsInParent());

System.out.println();

System.out.println("add shadow");

// 2. add shadow

Button button2 = new Button();

button2.setEffect(new BoxBlur());

System.out.println("button2=" + button2.getLayoutBounds());

System.out.println("button2=" + button2.getBoundsInLocal());

System.out.println("button2=" + button2.getBoundsInParent());

System.out.println();

System.out.println("add transformation");

// 3. add transformation

Button button3 = new Button();

//button3.setRotate(60);

button3.getTransforms().add(new Translate(150, 75));

System.out.println("button3=" + button3.getLayoutBounds());

System.out.println("button3=" + button3.getBoundsInLocal());

System.out.println("button3=" + button3.getBoundsInParent());

root.getChildren().addAll(button1, new Group(button2), button3);

//primaryStage.show();

}

}

4 . 别名

Layout Bounds: 逻辑bound(logic bound)

BoundsInLocal: 现实上的bound(physical bound) (希望当前node包含Effect,Clip时候用的,另一种情况检测两个node有无碰撞)

BoundsInParent: 虚幻的bound(visual bound) (较少在code中使用到)

5 .这些Bound 处于不同的坐标系中

Layout Bounds: 在该node 的坐标系

BoundsInLocas:在该node 的坐标系

BoundsInParent:在该node 的parent的坐标系

了解这些不同的Bounds

6 . 每一个node 都有一对LayoutX和LayoutY以及一对translateX和translateY 来描述他们在坐标系中的位置

LayoutX 和LayoutY : 固定(stable) layout

translateX和translateY: 动态(dynamic) layout (animaiton中)

finalTranslationX = layoutX + translateX

finalTranslationY = layoutY + translateY

但是layoutX and layoutY 并不是就是直接确定了node的位置,它通常需要转为node的坐标系中的位置,通常需要补偿一个layoutBound.minX和layoutBound.minY

layoutX = finalX - node.getLayoutBounds().getMinX();

layoutY = finalY - node.getLayoutBounds().getMinY();

7 . 由于Bound 的存在,当你想设置坐标时候,记得加上边框左上角的位置的横纵坐标,推荐使用relocate() ,它会帮你补偿minX 和minY of layoutBound,自动完成6中提到的转换

8 . 当Parenty 为region 类时候,父节点有自己的位置策略,这时候忽略node layoutX,layoutY. 事实上只有当你的parent节点(layout manager)为Group或着Pane的时候,通过修改layoutX以及layoutY才能修改Node的位置

Node 的Size

当一个node可以随着父节点layout的调整自己的大小,该节点就是可以resize的.Node 的分为resizable和non-resize node.

re-sizable node: Regions, Controls, andWebView

non-resizable node : Group, Text, and Shapes

三个“大小”

Preferred size 最合适大小,当layout 足够满足的时候呈现的size

Minimum size 最小的大小,当resize的时候的最小大小

Maximum size 最大的大小, 当resize的时候的最大大小

对着三个size可以设置两个常量,

USE_COMPUTED_SIZE :依据的node的内容和属性计算

USE_PREF_SIZE:通常用来设置Minimum size和Maximum size保持和Preferred size一致

每个node也有6个属性来对应这个三个特性,这些属性的默认值为:USE_COMPUTED_SIZE

prefWidth,prefHeight

minWidth,minHeight

maxWidth,maxHeight

不要相信getXXX(getMaxWidth,getMinWidth,getPre...),通常这些方法返回的值并没有真实反映node的大小

使用以下方法:

double prefWidth(double height)

double prefHeight(double width)

double minWidth(double height)

double minHeight(double width)

double maxWidth(double height)

double maxHeight(double width)

通过传入-1来获得content bias 边的长度,再根据该长度算得相应的宽或者高

Paste_Image.png

public class NodeSizes extends Application {

public static void main(String[] args) {

Application.launch(args);

}

@Override

public void start(Stage stage) {

Button btn = new Button("Hello JavaFX!");

HBox root = new HBox();

root.getChildren().addAll(btn);

Scene scene = new Scene(root);

stage.setScene(scene);

stage.setTitle("Sizes of a Node");

stage.show();

// Print button's sizes

System.out.println("Before changing button properties:");

printSizes(btn);

// Change button's properties

btn.setWrapText(true);

btn.setPrefWidth(80);

stage.sizeToScene();

// Print button's sizes

System.out.println("\nAfter changing button properties:");

printSizes(btn);

}

public void printSizes(Button btn) {

System.out.println("btn.getContentBias() = " + btn.getContentBias());

System.out.println("btn.getPrefWidth() = " + btn.getPrefWidth() +

", btn.getPrefHeight() = " + btn.getPrefHeight());

System.out.println("btn.getMinWidth() = " + btn.getMinWidth() +

", btn.getMinHeight() = " + btn.getMinHeight());

System.out.println("btn.getMaxWidth() = " + btn.getMaxWidth() +

", btn.getMaxHeight() = " + btn.getMaxHeight());

double prefWidth = btn.prefWidth(-1);

System.out.println("btn.prefWidth(-1) = " + prefWidth +

", btn.prefHeight(prefWidth) = " + btn.prefHeight(prefWidth));

double minWidth = btn.minWidth(-1);

System.out.println("btn.minWidth(-1) = " + minWidth +

", btn.minHeight(minWidth) = " + btn.minHeight(minWidth));

double maxWidth = btn.maxWidth(-1);

System.out.println("btn.maxWidth(-1) = " + maxWidth +

", btn.maxHeight(maxWidth) = " + btn.maxHeight(maxWidth));

System.out.println("btn.getWidth() = " + btn.getWidth() +

", btn.getHeight() = " + btn.getHeight());

}

}

7 对于non-resizable node

prefWidth(double h), minWidth(double h), maxWidth(double h) 返回layoutBound的width

prefHeight(double w), minHeight(double w), maxHeight(double w) 返回layoutBound的height

8 关于managed node

当子节点的managedProperty设置为false的时候,父节点在layout布局的时候,就不会帮把计算如layoutboundbox. 这与visibleProperty的区别,尽管它不可见,父节点仍考虑它的布局。

public class SlidingLeftNodeTest extends Application {

public static void main(String[] args) {

Application.launch(args);

}

@Override

public void start(Stage stage) {

Button b1 = new Button("B1");

Button b2 = new Button("B2");

Button b3 = new Button("B3");

Button visibleBtn = new Button("Make Invisible");

// Add an action listener to the button to make b2 visible

// if it is invisible and invisible if it is visible

visibleBtn.setOnAction(e -> b2.setVisible(!b2.isVisible()));

// Bind the text property of the button to the visible

// property of the b2 button

visibleBtn.textProperty().bind(new When(b2.visibleProperty()).then("Make Invisible").otherwise("Make Visible"));

b2.managedProperty().bind(b2.visibleProperty());

HBox root = new HBox();

root.getChildren().addAll(visibleBtn, b1, b2, b3);

Scene scene = new Scene(root);

stage.setScene(scene);

stage.setTitle("Sliding to the Left");

stage.show();

}

}

java fx详解_Java fx 坐标揭秘相关推荐

  1. java condition详解_Java使用Condition控制线程通信的方法实例详解

    Java使用Condition控制线程通信的方法实例详解 发布于 2020-4-20| 复制链接 摘记: 本文实例讲述了Java使用Condition控制线程通信的方法.分享给大家供大家参考,具体如下 ...

  2. java 文件下载详解_Java 从网上下载文件的几种方式实例代码详解

    废话不多说了,直接给大家贴代码了,具体代码如下所示: package com.github.pandafang.tool; import java.io.BufferedOutputStream; i ...

  3. java技术详解_Java反射技术详解及实例解析

    前言 相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替 ...

  4. java list详解_Java 中 list 用法案例详解

    LIST是个容器接口可以理解为动态数组,传统数组必须定义好数组的个数才可以使用,而容器对象无须定义好数组下标总数,用add()方法即可添加新的成员对象,他可以添加的仅仅只能为对象,不能添加基本数据类型 ...

  5. java unsafe 详解_Java CAS操作与Unsafe类详解

    一.复习 计算机内存模型,synchronized和volatile关键字简介 二.两者对比 sychronized和volatile都解决了内存可见性问题 不同点: (1)前者是独占锁,并且存在者上 ...

  6. java pattern详解_JAVA正则表达式:Pattern类与Matcher类详解

    以下我们就分别来看看这两个类: 一.捕获组的概念 捕获组可以通过从左到右计算其开括号来编号,编号是从1 开始的.例如,在表达式 ((A)(B(C)))中,存在四个这样的组: 1        ((A) ...

  7. java while详解_Java while循环-Java while-嗨客网

    Java while教程 在 Java语言while语句详解 语法 while(condition){ //do something } 参数 参数 描述 while while 条件判断关键字 co ...

  8. java classpath详解_java Classpath全解(转)

    java Classpath全解(转)[@more@]java 的新入门者对classpath往往比较困惑,为何在开发环境中能运行的东东出去就不好,或在外面运行的东东挺溜的进了开发环境就死菜,烦死了! ...

  9. 位运算符Java与详解_java位运算符详解

    java位运算符详讲 一.位运算符分类    java中位运算符主要有:按位与&.按位或|.按位非~.按位异或^. 在使用时,需要将运算数都转换为二进制再进行运算,若为负数则使用补码表示.二. ...

最新文章

  1. ZOJ 2334 HDU 1512 Monkey King
  2. 序列化与字符流的操作
  3. vb.net 如何从文件中读取图像
  4. oracle登陆无效参数是啥意思,关于参数无效的详细介绍
  5. 堆排序(基于完全二叉树)
  6. uvalive4838(凸包+重心)
  7. Mysql数据库设计规范之四数据库操作行为规范
  8. Ext js 2.0 Overview(3) 组件生命周期
  9. 强大的图片浏览器---------增强、降低透明度、切换下一张
  10. Ui学习笔记---EasyUI的EasyLoader组件源码分析
  11. 如何区分PLC输入是源型输入还是漏型输入?
  12. DNS和DHCP之间有哪些区别
  13. 单片机led数码管显示c语言,各位大神,如何用C语言实现在数码管上实现1234同时亮...
  14. 操作系统学习笔记(一)
  15. QSqlRelationTableModel使用示例
  16. 《暗时间》读书笔记与读后感
  17. MATLAB 图像伪彩色处理
  18. 一些方便的LaTex在线编辑工具
  19. 金彩教育:选择关键词要参考哪些数据
  20. DP动态规划--乡村邮局问题-Post Office(POJ-1160)python

热门文章

  1. Python中ArcPy实现栅格图像文件由HDF格式批量转换为TIFF格式
  2. Jad - the fast Java Decompiler Jad Java反编译指令
  3. 到庄门前看时 手机杀毒软件
  4. 算法 - KMP算法原理顿悟有感
  5. [转]PCI配置空间简介
  6. 开源人才缺口持续扩大,Linux基金会揭秘开源就业真相
  7. Android应用的流量统计方法
  8. 常用工作方法总结(7S、SWOT分析、PDCA循环、SMART原则、6W2H、时间管理、WBS、二八原则)
  9. WordPress网站首页添加好看的四格小工具教程[WP教程]
  10. 初次使用hammer.js做卡片滑动效果