Skip to content

Instantly share code, notes, and snippets.

@io7m
Created August 10, 2019 15:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save io7m/20b071e11da2dcd96896a43fad6df644 to your computer and use it in GitHub Desktop.
Save io7m/20b071e11da2dcd96896a43fad6df644 to your computer and use it in GitHub Desktop.
Example scaling
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Transform;
import javafx.stage.Stage;
public final class ExampleScales extends Application
{
public ExampleScales()
{
}
private static final class Translation {
double x = 0.0;
double y = 0.0;
}
private static final class Scale {
double x = 128.0;
double y = 128.0;
}
@Override
public void start(final Stage stage)
{
final var translate = new Translation();
final var scale = new Scale();
/*
* A container pane for the entire view.
*/
final var containerPane = new AnchorPane();
containerPane.setStyle("-fx-background-color: #000000;");
containerPane.setPrefSize(640.0, 480.0);
/*
* A group that contains all objects in the container.
*/
final var containerGroup = new Pane();
containerPane.getChildren().add(containerGroup);
updateGroupTransform(translate, scale, containerGroup);
/*
* Some individual objects within the scene.
*/
createOneObject(containerGroup, 1.0, 1.0);
createOneObject(containerGroup, 3.0, 1.0);
createOneObject(containerGroup, 2.0, 2.5);
/*
* Buttons to control the "camera".
*/
makeCameraButtons(translate, scale, containerPane, containerGroup);
stage.setScene(new Scene(containerPane));
stage.titleProperty().setValue("Example");
stage.show();
}
private static void makeCameraButtons(
final Translation translate,
final Scale scale,
final AnchorPane containerPane,
final Pane containerGroup)
{
final var leftButton = new Button("LEFT");
leftButton.setPrefSize(64.0, 32.0);
final var rightButton = new Button("RIGHT");
rightButton.setPrefSize(64.0, 32.0);
final var upButton = new Button("UP");
upButton.setPrefSize(64.0, 32.0);
final var downButton = new Button("DOWN");
downButton.setPrefSize(64.0, 32.0);
AnchorPane.setLeftAnchor(rightButton, Double.valueOf(64.0));
AnchorPane.setTopAnchor(upButton, Double.valueOf(32.0));
AnchorPane.setTopAnchor(downButton, Double.valueOf(32.0));
AnchorPane.setLeftAnchor(downButton, Double.valueOf(64.0));
leftButton.setOnAction(event -> {
translate.x -= 0.5;
updateGroupTransform(translate, scale, containerGroup);
});
rightButton.setOnAction(event -> {
translate.x += 0.5;
updateGroupTransform(translate, scale, containerGroup);
});
upButton.setOnAction(event -> {
translate.y -= 0.5;
updateGroupTransform(translate, scale, containerGroup);
});
downButton.setOnAction(event -> {
translate.y += 0.5;
updateGroupTransform(translate, scale, containerGroup);
});
containerPane.getChildren().add(leftButton);
containerPane.getChildren().add(rightButton);
containerPane.getChildren().add(upButton);
containerPane.getChildren().add(downButton);
final var xZoomMButton = new Button("X-");
xZoomMButton.setPrefSize(64.0, 32.0);
final var xZoomPButton = new Button("X+");
xZoomPButton.setPrefSize(64.0, 32.0);
final var yZoomMButton = new Button("Y-");
yZoomMButton.setPrefSize(64.0, 32.0);
final var yZoomPButton = new Button("Y+");
yZoomPButton.setPrefSize(64.0, 32.0);
AnchorPane.setTopAnchor(xZoomMButton, Double.valueOf(64.0));
AnchorPane.setTopAnchor(xZoomPButton, Double.valueOf(64.0));
AnchorPane.setTopAnchor(yZoomMButton, Double.valueOf(96.0));
AnchorPane.setTopAnchor(yZoomPButton, Double.valueOf(96.0));
AnchorPane.setLeftAnchor(xZoomMButton, Double.valueOf(64.0));
AnchorPane.setLeftAnchor(yZoomPButton, Double.valueOf(64.0));
xZoomMButton.setOnAction(event -> {
scale.x -= 0.5;
updateGroupTransform(translate, scale, containerGroup);
});
xZoomPButton.setOnAction(event -> {
scale.x += 0.5;
updateGroupTransform(translate, scale, containerGroup);
});
yZoomMButton.setOnAction(event -> {
scale.y -= 0.5;
updateGroupTransform(translate, scale, containerGroup);
});
yZoomPButton.setOnAction(event -> {
scale.y += 0.5;
updateGroupTransform(translate, scale, containerGroup);
});
containerPane.getChildren().add(xZoomMButton);
containerPane.getChildren().add(xZoomPButton);
containerPane.getChildren().add(yZoomMButton);
containerPane.getChildren().add(yZoomPButton);
}
private static void createOneObject(
final Pane containerGroup,
final double x,
final double y)
{
/*
* A single object container.
*/
final var objectTransformTranslate = Affine.translate(x, y);
final var objectPane = new Pane();
objectPane.setStyle("-fx-background-color: #aaaaaa;");
objectPane.getTransforms().add(objectTransformTranslate);
objectPane.setPrefSize(1.0, 1.0);
containerGroup.getChildren().add(objectPane);
/*
* A single object internal pane. All objects must be placed within this pane.
*/
final var objectInternalPane = new Pane();
objectPane.getChildren().add(objectInternalPane);
/*
* Configure the internal pane such that the scaling transform of the container
* pane is inverted. This allows us to work with "scene" pixel positions inside
* the container (so that things like labels can actually render correctly).
*/
containerGroup.localToParentTransformProperty()
.addListener((observable, oldValue, newValue) -> determineInverseScale(objectInternalPane, newValue));
determineInverseScale(objectInternalPane, containerGroup.getLocalToParentTransform());
final var text = new Label("XYZ");
objectInternalPane.getChildren().add(text);
}
private static void updateGroupTransform(
final Translation translate,
final Scale scale,
final Node containerGroup)
{
final var transforms = containerGroup.getTransforms();
transforms.clear();
transforms.add(Affine.scale(scale.x, scale.y));
transforms.add(Transform.translate(translate.x, translate.y));
}
private static void determineInverseScale(
final Pane pane,
final Transform newValue)
{
final var scaleX = newValue.getMxx();
final var scaleY = newValue.getMyy();
final var scale = Affine.scale(1.0 / scaleX, 1.0 / scaleY);
final var transforms = pane.getTransforms();
transforms.clear();
transforms.add(scale);
}
public static void main(final String[] args)
{
Application.launch(ExampleScales.class, args);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment