Listen for transformation changes - java

Is there way to listen for transformation changes? I'd like to get notified when for example a cube has turned. Especially I'am interested in getLocalToSceneTransform.
Here is my try:
#Override
public void start(Stage primaryStage) throws Exception {
final Group root = new Group();
final Scene scene = new Scene(root);
final Box cube = new Box(1, 1, 1);
cube.setRotationAxis(Rotate.Y_AXIS);
cube.setMaterial(new PhongMaterial(Color.RED));
root.getChildren().add(cube);
cube.getLocalToSceneTransform().addEventHandler(TransformChangedEvent.TRANSFORM_CHANGED, (e) -> {
// never get called
System.out.println("Transformation has changed");
});
final Camera camera = new PerspectiveCamera(true);
camera.setTranslateZ(-4);
scene.setCamera(camera);
final Timeline turnCube = new Timeline();
turnCube.getKeyFrames().add(new KeyFrame(Duration.seconds(0), new KeyValue(cube.rotateProperty(), 0)));
turnCube.getKeyFrames().add(new KeyFrame(Duration.seconds(5), new KeyValue(cube.rotateProperty(), 360)));
turnCube.setCycleCount(Timeline.INDEFINITE);
turnCube.play();
primaryStage.setWidth(1024);
primaryStage.setHeight(768);
primaryStage.setScene(scene);
primaryStage.show();
}
While the cube is turned the EventHandler get never called.

You can add a changeListener to the cube's localToSceneTransformProperty() to get notified when the cube is rotated.
cube.localToSceneTransformProperty().addListener((value, oldValue, newValue) -> {
System.out.println("Transformation has changed");
});

Related

How to change between wireframe and solid in javafx

3d software allow user to change draw mode dinamically. It can be implemented on javafx ?
Changing draw mode with radio buttons
In this approach a Box instance change its DrawMode with radiobuttons.
This is a single class javafx you can try .
App.java
public class App extends Application {
#Override
public void start(Stage stage) {
var perspective = new PerspectiveCamera(true);
perspective.setNearClip(0.1);
perspective.setFarClip(500);
perspective.setTranslateZ(-150);
Shape3D cube = new Box(50, 50, 50);
cube.setCullFace(CullFace.NONE);
cube.setMaterial(new PhongMaterial(Color.CORAL));
var toggleGroup = new ToggleGroup();
var solid = new RadioButton("solid");
solid.setToggleGroup(toggleGroup);
solid.setSelected(true);
var wire = new RadioButton("wireframe");
wire.setToggleGroup(toggleGroup);
var hBox = new HBox(solid, wire);
toggleGroup.selectedToggleProperty().addListener((o) -> {
Toggle selectedToggle = toggleGroup.getSelectedToggle();
if (selectedToggle == solid) {
cube.setDrawMode(DrawMode.FILL);
}
if (selectedToggle == wire) {
cube.setDrawMode(DrawMode.LINE);
}
});
var group3d = new Group(perspective, cube);
var subscene = new SubScene(group3d, 300, 400, true, SceneAntialiasing.BALANCED);
subscene.setCamera(perspective);
var stack = new StackPane(subscene, hBox);
stage.setScene(new Scene(stack, 300, 400));
stage.show();
}
public static void main(String[] args) {
launch();
}
}

Javafx: Dialog y position doesn't work properly

Please, consider the following code:
public class JavaFxTest4 extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Button button = new Button();
button.setText("dialog");
button.setOnAction((e) -> {
Dialog<?> d = new Dialog<>();
final Window window = d.getDialogPane().getScene().getWindow();
Stage stage = (Stage) window;
stage.setMinHeight(450);
stage.setMaxHeight(450);
stage.setHeight(450);
stage.setMinWidth(600);
stage.setMaxWidth(600);
stage.setWidth(600);
window.setY(300); //<---- note this line
window.setX(660); //<---- note this line
d.showAndWait();
});
VBox root = new VBox();
root.getChildren().addAll(button);
var scene = new Scene(root, 1920, 1000);
primaryStage.setScene(scene);
primaryStage.show();
}
}
As you can see window position is 660 (x) and 300 (y). And this is the result:
As you can see x position is correct, but y position is not. Is this a bug or I misunderstand something? I use javafx 19-ea+3 and openjdk version "14.0.2" on Ubuntu 20.
It is a bug in JavaFX. Issue is here

JavaFX CheckBoxTreeItem graphic disappear/appear when expanding/collapsing

I'm trying to make TreeView with CheckBoxTreeItems. When I collapse/expand a CheckBoxTreeItems the image I set up does not display correctly. I googled but I couldn't find correct answer. On Stack Overflow, I found a similar problem, but I didn't get a valid answer.
E.g
JavaFX CheckBoxTreeItem graphic disappear when siblings collapse
JavaFX CheckBoxTreeItem: Graphic disappears if graph is extended
Any ideas?
public class ClientApplication extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(final Stage stage) {
ImageView folderIcon = new ImageView();
Image folderImage = new Image("image/folder.png");
folderIcon.setImage(folderImage);
folderIcon.setFitWidth(16);
folderIcon.setFitHeight(16);
CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<String>("folder", folderIcon);
rootItem.setExpanded(true);
for (int i = 0; i < 4; i++) {
CheckBoxTreeItem<String> checkBoxTreeItem = new CheckBoxTreeItem<String>("Sample" + (i + 1), folderIcon);
rootItem.getChildren().add(checkBoxTreeItem);
}
final TreeView<String> tree = new TreeView<String>(rootItem);
tree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());
tree.setRoot(rootItem);
tree.setShowRoot(true);
StackPane root = new StackPane();
root.getChildren().add(tree);
stage.setScene(new Scene(root, 300, 250));
stage.show();
}
}
enter image description here
I tried to use the ideas provided by #Jai,But when I click the expand/collapse icon, there is still a problem.Attachment is a screenshot.Thanks in advance.
enter image description here
ImageView is a JavaFX control. This means that each instance represents a unique control you see on your screen. You should never use the same instance for multiple locations in your GUI.
On the other hand, Image represents an image (i.e. an array of pixel data), so it is reusable.
This should work:
#Override
public void start(final Stage stage) {
final Image folderImage = new Image("image/folder.png");
CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<String>("folder", createImageView(folderImage));
rootItem.setExpanded(true);
for (int i = 0; i < 4; i++) {
CheckBoxTreeItem<String> checkBoxTreeItem = new CheckBoxTreeItem<String>("Sample" + (i + 1), createImageView(folderImage));
rootItem.getChildren().add(checkBoxTreeItem);
}
final TreeView<String> tree = new TreeView<String>(rootItem);
tree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());
tree.setRoot(rootItem);
tree.setShowRoot(true);
StackPane root = new StackPane();
root.getChildren().add(tree);
stage.setScene(new Scene(root, 300, 250));
stage.show();
}
private ImageView createImageView(Image folderImage) {
ImageView folderIcon = new ImageView();
folderIcon.setImage(folderImage);
folderIcon.setFitWidth(16);
folderIcon.setFitHeight(16);
return folderIcon;
}

How to check if a line intersect an image

Here is my following code:
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
Scene scene = new Scene(root, 500, 500, Color.WHITE);
ImageView image = new ImageView(new Image(getClass().getResourceAsStream("dice.jpeg")));
image.setX(35);
image.setY(225);
image.setFitWidth(50);
image.setFitHeight(70);
root.getChildren().add(image);
Line line = new Line(20, 40, 120, 40);
line.setStroke(Color.RED);
line.setStrokeWidth(10);
root.getChildren().add(line);
if (line.getBoundsInParent().intersects(image.getBoundsInParent())) {
System.out.println("intersect");
}
Timeline timeline = new Timeline(
new KeyFrame(
Duration.seconds(2),
new KeyValue(line.translateYProperty(), 600)
));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.setAutoReverse(false);
timeline.play();
primaryStage.setScene(scene);
primaryStage.show();
}
I want this System.out.println("intersect") message to be print when the line and image intersect, but when I run my code it doesn't work. Can anyone please tell me what am I doing wrong? Any help is appreciated!
I have come up with a solution. This involves using a thread to check all the time while the other code is still running. The error in your code is it only checked once when the animation had not started running.
Obviously, my code is not perfect so you may want to clean it up to suit your needs:
public class Test extends Application{
public static void main(String[] args) {
Test.launch(args);
//The thread which checks continues to run so you have to stop it
//(There is definitly a better way to do this)
System.exit(0);
}
#Override
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
Scene scene = new Scene(root, 500, 500, Color.WHITE);
ImageView image = new ImageView(new Image(getClass().getResourceAsStream("dice.jpeg")));
image.setX(35);
image.setY(225);
image.setFitWidth(50);
image.setFitHeight(70);
root.getChildren().add(image);
Line line = new Line(20, 40, 120, 40);
line.setStroke(Color.RED);
line.setStrokeWidth(10);
root.getChildren().add(line);
//new code
Thread t = new Thread(){
#Override
public void run(){
while(true){
try {
//you could add a Thread.sleep so it only checks every x miliseconds
Thread.sleep(40);
if (line.getBoundsInParent().intersects(image.getBoundsInParent())) {
System.out.println("intersect");
}
} catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
t.start();
//end of new code
Timeline timeline = new Timeline(
new KeyFrame(
Duration.seconds(2),
new KeyValue(line.translateYProperty(), 600)
));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.setAutoReverse(false);
timeline.play();
primaryStage.setScene(scene);
primaryStage.show();
}
}

Why does Transform in JavaFX looks like 3D?

Looks like Transform class in JavaFX contains 3 coordinates (x, y and z).
What will happen if I rotate out of plane? Will it do perspective?
UPDATE
Actually object disappears if rotated out of plane even by 1 degree. Why?
public class TransformTry extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Drawing Operations Test");
Group root = new Group();
Canvas canvas = new Canvas(300, 250);
//canvas.getTransforms().add(new Rotate(1, new Point3D(0, 1, 0))); // square disappears
canvas.getTransforms().add(new Rotate(1, new Point3D(0, 0, 1))); // rotates correctly
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.strokeRect(-50, -50, 100, 100);
root.getChildren().add(canvas);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
UPDATE 2
I found a way to use perspective camera, but it works strange: it looks always from above the center of a window, so out-of-plane object changes on window resize:
public class ShapeTry01 extends Application {
#Override
public void start(Stage stage) throws Exception {
Shape shape = new Rectangle(100,100,50,50);
shape.setStroke(Color.RED);
shape.setFill(null);
Group group = new Group();
group.getChildren().add(shape);
//group.getTransforms().add(new Rotate(10, new Point3D(0, 0, 1)));
group.getTransforms().add(new Rotate(10, new Point3D(0, 1, 0)));
PerspectiveCamera camera = new PerspectiveCamera();
camera.setFieldOfView(45);
Scene scene = new Scene(group);
scene.setCamera( camera );
stage.setTitle("ShapeTry01");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
JavaFX 2 was started with 3D in mind, thus a lot of API has z coordinate mentioned. But actually useful 3D was added only in JavaFX8 (to be released in next year).
You can see documentation here: http://docs.oracle.com/javafx/8/3d_graphics/jfxpub-3d_graphics.htm and try developers preview: https://jdk8.java.net/download.html

Categories