I keep playing with 3D in JavaFX.
I added SubScene
with some Box
to my demo app but the edges of the Box
are nasty. How can I smooth them without using SceneAntialiasing.BALANCED
in constructor? I've seen there is possibility to add antiAliasing=""
in FXML file, but then I don't know what should be putted as the parameter. Word BALANCED
is not working.
Controller.java
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.fxml.FXML;
import javafx.scene.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.util.Duration;
public class Controller{
@FXML
private SubScene subscene;
@FXML
private AnchorPane pane;
private Box box= new Box();
private PerspectiveCamera camera = new PerspectiveCamera(true);
private Group group = new Group();
final Rotate rx = new Rotate(0, Rotate.X_AXIS);
final Rotate ry = new Rotate(0, Rotate.Y_AXIS);
final Rotate rz = new Rotate(0, Rotate.Z_AXIS);
private Timeline animation;
@FXML
void initialize() {
box.setMaterial(new PhongMaterial(Color.ORANGE));
box.setDepth(10);
box.setWidth(10);
box.setHeight(10);
rx.setAngle(90);
ry.setAngle(25);
box.getTransforms().addAll(rz, ry, rx);
group.getChildren().add(box);
animation = new Timeline();
animation.getKeyFrames().addAll(
new KeyFrame(Duration.ZERO,
new KeyValue(box.depthProperty(), 0d),
new KeyValue(box.translateYProperty(),400d)),
new KeyFrame(Duration.seconds(5),
new KeyValue(box.depthProperty(), 800d),
new KeyValue(box.translateYProperty(), 0d)));
animation.setCycleCount(Timeline.INDEFINITE);
camera.getTransforms().add(new Translate(0, 0, -80));
camera.getTransforms().addAll (
new Rotate(-35, Rotate.X_AXIS),
new Translate(0, 0, 10)
);
subscene.setRoot(group);
subscene.setCamera(camera);
animation.play();
}
}
main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.SubScene?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Region?>
<AnchorPane fx:id="pane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="check.brakes.Controller">
<children>
<SubScene fx:id="subscene" height="697.0" layoutX="78.0" layoutY="54.0" width="643.0" AnchorPane.bottomAnchor="49.0" AnchorPane.leftAnchor="78.0" AnchorPane.rightAnchor="79.0" AnchorPane.topAnchor="54.0" >
<root>
<Region />
</root>
</SubScene>
<Button layoutX="196.0" layoutY="186.0" mnemonicParsing="false" text="Button" />
<Button fx:id="btn2" layoutX="450.0" layoutY="186.0" mnemonicParsing="false" text="Button" />
<Label layoutX="386.0" layoutY="36.0" text="test" />
<Label layoutX="381.0" layoutY="753.0" text="test 2" />
</children>
</AnchorPane>
Is there any other way to achieve that?
Since SceneAntialiasing
is not an enum you can't use the constant name in an attribute. However, the SubScene
constructor does annotate the SceneAntialiasing
parameter with @NamedArg
, which means it can be injected when created via FXML. You just need to use an element in combination with fx:constant
instead of an attribute. For example:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.SubScene?>
<?import javafx.scene.SceneAntialiasing?>
<SubScene xmlns="http://javafx.com/javafx/12.0.1" xmlns:fx="http://javafx.com/fxml/1">
<antiAliasing>
<SceneAntialiasing fx:constant="BALANCED"/>
</antiAliasing>
</SubScene>
Loading the above with:
import java.io.IOException;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.SubScene;
import javafx.stage.Stage;
public final class App extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
SubScene scene = FXMLLoader.load(getClass().getResource(...));
System.out.println(scene.getAntiAliasing());
Platform.exit();
}
}
Resulted in BALANCED
being printed.