下面列出了怎么用javafx.scene.transform.Transform的API类实例代码及写法,或者点击链接到github查看源代码。
/** Update lines that indicate model's size in edit mode */
private void updateModelSizeIndicators()
{
int width = model.propWidth().getValue();
int height = model.propHeight().getValue();
final ObservableList<Transform> transforms = widget_parent.getTransforms();
if (transforms.size() > 0 && transforms.get(0) instanceof Scale)
{
final Scale scale = (Scale) transforms.get(0);
width *= scale.getX();
height *= scale.getY();
}
horiz_bound.setStartY(height);
horiz_bound.setEndX(width);
horiz_bound.setEndY(height);
vert_bound.setStartX(width);
vert_bound.setEndY(height);
vert_bound.setEndX(width);
}
/**
* Unregisters all previously registered listeners.
*/
public void unregister() {
if (!isRegistered()) {
return;
}
// remove bounds listener
observed.layoutBoundsProperty().removeListener(layoutBoundsListener);
observed.boundsInLocalProperty().removeListener(boundsInLocalListener);
observed.boundsInParentProperty()
.removeListener(boundsInParentListener);
// remove transform listeners
for (ChangeListener<Transform> l : localToParentTransformListeners
.keySet()) {
localToParentTransformListeners.get(l)
.localToParentTransformProperty().removeListener(l);
}
// reset fields
parent = null;
observed = null;
localToParentTransformListeners.clear();
}
public List<Shape> getIntersectedShapes(final Bounds selectionBorder) {
final Rectangle selectionRec = new Rectangle(selectionBorder.getMinX() + Canvas.ORIGIN.getX(),
selectionBorder.getMinY() + Canvas.ORIGIN.getY(), selectionBorder.getWidth(), selectionBorder.getHeight());
// Transforming the selection rectangle to match the transformation of the canvas.
selectionRec.getTransforms().setAll(getLocalToSceneTransform());
return getViews().getChildren().stream().filter(view -> {
Bounds bounds;
final Transform transform = view.getLocalToParentTransform();
if(transform.isIdentity()) {
bounds = selectionBorder;
}else {
try {
bounds = transform.createInverse().transform(selectionBorder);
}catch(final NonInvertibleTransformException ex) {
bounds = selectionBorder;
}
}
return view.intersects(bounds) &&
((ViewShape<?>) view).getActivatedShapes().stream().anyMatch(sh -> !javafx.scene.shape.Shape.intersect(sh, selectionRec).getLayoutBounds().isEmpty());
})
.map(view -> (Shape) view.getUserData())
.collect(Collectors.toList());
}
NodeDetailPaneInfo(final FXConnectorEventDispatcher dispatcher, final StageID stageID) {
super(dispatcher, stageID, DetailPaneType.NODE);
transformListener = new ListChangeListener<Transform>() {
@Override public void onChanged(final Change<? extends Transform> c) {
updateDetail("transforms");
}
};
}
public static AffineTransform3D fromTransformFX(final Transform transform)
{
final AffineTransform3D ret = new AffineTransform3D();
ret.set(
transform.getMxx(), transform.getMxy(), transform.getMxz(), transform.getTx(),
transform.getMyx(), transform.getMyy(), transform.getMyz(), transform.getTy(),
transform.getMzx(), transform.getMzy(), transform.getMzz(), transform.getTz()
);
return ret;
}
/** @return Zoom factor, 1.0 for 1:1 */
public double getZoom()
{
final List<Transform> transforms = widget_parent.getTransforms();
if (transforms.isEmpty() ||
transforms.size() > 1 ||
! (transforms.get(0) instanceof Scale))
return 1.0;
// Have one 'scale'
final Scale scale = (Scale) transforms.get(0);
// Expect scaling in X == Y, but just in case return average
return ( scale.getX() + scale.getY() ) / 2.0;
}
private void removeAllFocusTransforms() {
ObservableList<Transform> allTrans = focusGroup.getTransforms();
List<Object> toRemove = Arrays.asList(allTrans.toArray());
for (Object t : toRemove) {
allTrans.remove(t);
}
}
private void applyTransform(Affine dst, Transform transform) {
AffineTransform affineTransform = FX2Geometry
.toAffineTransform(dst);
AffineTransform result = affineTransform
.concatenate(FX2Geometry.toAffineTransform(transform));
setAffine(dst, result);
}
/**
* Checks if the given Transform contains NaN values. Returns
* <code>true</code> if no NaN values are found, otherwise <code>false/
* <code>.
*
* @param t
* @return
*/
private boolean isValidTransform(Transform t) {
if (Double.isNaN(t.getMxx()) || Double.isInfinite(t.getMxx())) {
return false;
}
if (Double.isNaN(t.getMxy()) || Double.isInfinite(t.getMxy())) {
return false;
}
if (Double.isNaN(t.getMxz()) || Double.isInfinite(t.getMxz())) {
return false;
}
if (Double.isNaN(t.getMyx()) || Double.isInfinite(t.getMyx())) {
return false;
}
if (Double.isNaN(t.getMyy()) || Double.isInfinite(t.getMyy())) {
return false;
}
if (Double.isNaN(t.getMyz()) || Double.isInfinite(t.getMyz())) {
return false;
}
if (Double.isNaN(t.getMzx()) || Double.isInfinite(t.getMzx())) {
return false;
}
if (Double.isNaN(t.getMzy()) || Double.isInfinite(t.getMzy())) {
return false;
}
if (Double.isNaN(t.getMzz()) || Double.isInfinite(t.getMzz())) {
return false;
}
if (Double.isNaN(t.getTx()) || Double.isInfinite(t.getTx())) {
return false;
}
if (Double.isNaN(t.getTy()) || Double.isInfinite(t.getTy())) {
return false;
}
if (Double.isNaN(t.getTz()) || Double.isInfinite(t.getTz())) {
return false;
}
return true;
}
@Override
protected List<? extends Object> doGetContentChildren() {
Graph nestedGraph = getContent().getNestedGraph();
if (nestedGraph == null) {
return Collections.emptyList();
}
// only show children when zoomed in
Transform tx = getVisual().getLocalToSceneTransform();
double scale = FX2Geometry.toAffineTransform(tx).getScaleX();
if (scale > ZOOMLEVEL_SHOW_NESTED_GRAPH) {
return Collections.singletonList(nestedGraph);
}
return Collections.emptyList();
}
/**
* Transforms the given {@link List} of
* {@link IBendableContentPart.BendPoint}s according to the change
* specified by the given current and final {@link Affine}
* transformations.
*
* @param bendPoints
* The {@link List} of
* {@link IBendableContentPart.BendPoint}s to transform.
* @param currentTransform
* The current {@link Affine} transformation.
* @param totalTransform
* The final {@link Affine} transformation.
* @return The given, transformed {@link List} of
* {@link IBendableContentPart.BendPoint}s.
*/
static List<BendPoint> transform(List<BendPoint> bendPoints,
Affine currentTransform, Affine totalTransform) {
// compute delta transform
Affine inverse;
try {
inverse = currentTransform.createInverse();
} catch (NonInvertibleTransformException e) {
throw new RuntimeException(e);
}
Transform deltaTransform = new Affine(
inverse.createConcatenation(totalTransform));
// optimize for identity transform
if (deltaTransform.isIdentity()) {
return bendPoints;
}
// System.out.println("Transform by " + deltaTransform.getTx() + ",
// "
// + deltaTransform.getTy() + ".");
AffineTransform tx = FX2Geometry.toAffineTransform(deltaTransform);
// transform unattached bend points in-place
for (BendPoint bp : bendPoints) {
if (!bp.isAttached()) {
bp.getPosition().transform(tx);
}
}
return bendPoints;
}
private void startTimer(){
timer = new AnimationTimer() {
@Override
public void handle(long now) {
Transform ct = (camera != null) ? camera.getLocalToSceneTransform() : null;
if(ct != null){
affine.setTx(ct.getTx());
affine.setTy(ct.getTy());
affine.setTz(ct.getTz());
}
}
};
timer.start();
}
protected void makeImage() {
try {
if (webView == null || webEngine == null || !webView.isVisible()) {
return;
}
synchronized (this) {
if (task != null) {
return;
}
final double rotate = webView.getRotate();
webView.setRotate(0);
// webEngine.executeScript("document.body.style.backgroundColor = '"
// + FxmlColor.rgb2css((Color) bgRect.getFill()) + "'; opacity:" + opacity);
// webView.setOpacity(1);
// webEngine.executeScript("document.body.style.backgroundColor = 'rgba(0,0,0,0)';");
// http://news.kynosarges.org/2017/02/01/javafx-snapshot-scaling/
double scale = FxmlControl.dpiScale();
final WritableImage snap = new WritableImage(
(int) Math.round(webView.getWidth() * scale),
(int) Math.round(webView.getHeight() * scale));
final SnapshotParameters parameters = new SnapshotParameters();
parameters.setTransform(Transform.scale(scale, scale));
parameters.setFill(Color.TRANSPARENT);
webView.snapshot(parameters, snap);
if (!parent.editable.get()) {
return;
}
task = new SingletonTask<Void>() {
private Image transparent, blended;
@Override
protected boolean handle() {
try {
transparent = FxmlImageManufacture.replaceColor(snap,
Color.WHITE, Color.TRANSPARENT, 0);
blended = FxmlImageManufacture.drawHTML(imageController.imageView.getImage(),
transparent, imageController.maskRectangleData,
(Color) bgRect.getFill(), opacity, arc,
(int) rotate, marginsWidth);
if (task == null || isCancelled()) {
return false;
}
return blended != null;
} catch (Exception e) {
logger.error(e.toString());
return false;
}
}
@Override
protected void whenSucceeded() {
if (isPreview) {
webView.setRotate(rotate);
// ImageViewerController controller1
// = (ImageViewerController) openStage(CommonValues.ImageFxml);
// controller1.loadImage(transparent);
ImageViewerController controller
= (ImageViewerController) openStage(CommonValues.ImageViewerFxml);
controller.loadImage(blended);
controller.setAsPopped();
} else {
parent.updateImage(ImageOperation.RichText, null, null, blended, cost);
webView = null;
}
}
};
parent.openHandlingStage(task, Modality.WINDOW_MODAL);
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
} catch (Exception e) {
logger.error(e.toString());
}
}
@Override
public Scene createScene() {
BorderPane root = new BorderPane();
infiniteCanvas = new InfiniteCanvas();
root.setCenter(infiniteCanvas);
infiniteCanvas.getContentGroup().getChildren().addAll(
rect(25, 25, 100, 50, Color.BLUE),
rect(25, 200, 25, 50, Color.BLUE),
rect(150, 100, 75, 75, Color.BLUE),
rect(-100, -100, 30, 60, Color.CYAN),
rect(75, 75, 150, 150, Color.RED));
// translate to top-left most content node
Bounds canvasBounds = infiniteCanvas.getContentBounds();
double minx = canvasBounds.getMinX();
double miny = canvasBounds.getMinY();
infiniteCanvas.setHorizontalScrollOffset(-minx);
infiniteCanvas.setVerticalScrollOffset(-miny);
infiniteCanvas.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (MouseButton.SECONDARY.equals(event.getButton())) {
// determine pivot in content group
Group contentGroup = infiniteCanvas.getContentGroup();
Point2D contentPivot = contentGroup
.sceneToLocal(event.getSceneX(), event.getSceneY());
double zoomFactor = event.isControlDown() ? 4d / 5 : 5d / 4;
// compute zoom transformation
Affine tx = infiniteCanvas.getContentTransform();
AffineTransform at = FX2Geometry.toAffineTransform(tx);
at.concatenate(new AffineTransform()
.translate(contentPivot.getX(), contentPivot.getY())
.scale(zoomFactor, zoomFactor)
.translate(-contentPivot.getX(),
-contentPivot.getY()));
Affine affine = Transform.affine(at.getM00(), at.getM01(),
at.getM10(), at.getM11(), at.getTranslateX(),
at.getTranslateY());
infiniteCanvas.setContentTransform(affine);
}
}
});
return new Scene(root, 400, 300);
}
@Override
protected void localToParentTransformChanged(Node observed, Transform oldTransform, Transform newTransform) {
refreshVisual();
}
@Override
protected void doAttachToAnchorageVisual(
IVisualPart<? extends Node> anchorage, String role) {
// enable visual refresh now that we have an anchorage
setRefreshVisual(true);
// we only add one visual change listener per anchorage, so we need to
// keep track of the number of links to an anchorage (roles)
int count = anchorageLinkCount.get(anchorage) == null ? 0
: anchorageLinkCount.get(anchorage);
if (count == 0) {
Node anchorageVisual = anchorage.getVisual();
final boolean doIt[] = new boolean[] { true };
VisualChangeListener listener = new VisualChangeListener() {
@Override
protected void boundsInLocalChanged(Bounds oldBounds,
Bounds newBounds) {
if (doIt[0]) {
doIt[0] = false;
refreshVisual();
doIt[0] = true;
}
}
@Override
protected void localToParentTransformChanged(Node observed,
Transform oldTransform, Transform newTransform) {
if (doIt[0]) {
doIt[0] = false;
refreshVisual();
doIt[0] = true;
}
}
};
visualChangeListeners.put(anchorage, listener);
listener.register(anchorage.getVisual(), getVisual());
// for connections, we need to refresh the handle if the
// connection's geometry changes, too
if (anchorageVisual instanceof Connection) {
Connection connection = (Connection) anchorageVisual;
connection.anchorsUnmodifiableProperty()
.addListener(geometryListener);
}
}
anchorageLinkCount.put(anchorage, count + 1);
}
@Override
protected void doAttachToAnchorageVisual(
IVisualPart<? extends Node> anchorage, String role) {
setRefreshVisual(true);
// we only add one visual change listener per anchorage, so we need to
// keep track of the number of links to an anchorage (roles)
int count = anchorageLinkCount.get(anchorage) == null ? 0
: anchorageLinkCount.get(anchorage);
if (count == 0) {
Node anchorageVisual = anchorage.getVisual();
final boolean doIt[] = new boolean[] { true };
VisualChangeListener listener = new VisualChangeListener() {
@Override
protected void boundsInLocalChanged(Bounds oldBounds,
Bounds newBounds) {
if (doIt[0]) {
doIt[0] = false;
refreshVisual();
doIt[0] = true;
}
}
@Override
protected void localToParentTransformChanged(Node observed,
Transform oldTransform, Transform newTransform) {
if (doIt[0]) {
doIt[0] = false;
refreshVisual();
doIt[0] = true;
}
}
};
visualChangeListeners.put(anchorage, listener);
listener.register(anchorage.getVisual(), getVisual());
// for connections, we need to refresh the handle if the
// connection's geometry changes, too
if (anchorageVisual instanceof Connection) {
Connection connection = (Connection) anchorageVisual;
connection.pointsUnmodifiableProperty()
.addListener(geometryListener);
}
}
anchorageLinkCount.put(anchorage, count + 1);
}
/**
* Updates the transformation matrix.
* can change the Translate for fixed distance
*/
default void updateMatrix(){
Transform cam = getOther().getLocalToSceneTransform(),
self = getBillboardNode().getLocalToSceneTransform();
Bounds b;
double cX,
cY,
cZ;
if(!(getBillboardNode() instanceof Shape3D)){
b = getBillboardNode().getBoundsInLocal();
cX = b.getWidth() / 2;
cY = b.getHeight() / 2;
cZ = b.getDepth() / 2;
}else{
cX = self.getTx();
cY = self.getTy();
cZ = self.getTz();
}
Point3D camPos = new Point3D(cam.getTx(), cam.getTy(), cam.getTz());
Point3D selfPos = new Point3D(cX, cY, cZ);
Vector3D up = Vector3D.UP,
forward = new Vector3D(
(selfPos.getX()) - camPos.getX(),
(selfPos.getY()) - camPos.getY(),
(selfPos.getZ()) - camPos.getZ()
).toNormal(),
right = up.crossProduct(forward).toNormal();
up = forward.crossProduct(right).toNormal();
switch(getBillboardMode()){
case SPHERICAL:
affine.setMxx(right.x); affine.setMxy(up.x); affine.setMzx(forward.x);
affine.setMyx(right.y); affine.setMyy(up.y); affine.setMzy(forward.y);
affine.setMzx(right.z); affine.setMzy(up.z); affine.setMzz(forward.z);
affine.setTx(cX * (1 - affine.getMxx()) - cY * affine.getMxy() - cZ * affine.getMxz());
affine.setTy(cY * (1 - affine.getMyy()) - cX * affine.getMyx() - cZ * affine.getMyz());
affine.setTz(cZ * (1 - affine.getMzz()) - cX * affine.getMzx() - cY * affine.getMzy());
break;
case CYLINDRICAL:
affine.setMxx(right.x); affine.setMxy(0); affine.setMzx(forward.x);
affine.setMyx(0); affine.setMyy(1); affine.setMzy(0);
affine.setMzx(right.z); affine.setMzy(0); affine.setMzz(forward.z);
affine.setTx(cX * (1 - affine.getMxx()) - cY * affine.getMxy() - cZ * affine.getMxz());
affine.setTy(cY * (1 - affine.getMyy()) - cX * affine.getMyx() - cZ * affine.getMyz());
affine.setTz(cZ * (1 - affine.getMzz()) - cX * affine.getMzx() - cY * affine.getMzy());
break;
}
}
/**
* This method is called upon a local-to-parent-transform change.
*
* @param observed
* The {@link Node} whose local-to-parent-transform changed.
* @param oldTransform
* The old {@link Transform}.
* @param newTransform
* The new {@link Transform}.
*/
protected abstract void localToParentTransformChanged(Node observed,
Transform oldTransform, Transform newTransform);
/**
* Converts the given JavaFX {@link Transform} to an {@link AffineTransform}
* .
*
* @param t
* The JavaFX {@link Transform} to convert.
* @return The new {@link AffineTransform}.
*/
public static final AffineTransform toAffineTransform(Transform t) {
return new AffineTransform(t.getMxx(), t.getMyx(), t.getMxy(), t.getMyy(), t.getTx(), t.getTy());
}