When using a Timeline transition on a translateXProperty of a shape, the image disappears when the container is rotated to 90 degrees (and other 'vertical' angles) AND setCache(true) is used. 89 degrees works fine. Code to demonstrate follows:
package application;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.CacheHint;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application
{
// The meat of the problem is here ...
// If we choose a combination of setCache(true) and a 90 degree rotation (or multiple thereof) the image disappears
private void startAnimation()
{
disableSwitches(true);
if (cacheCheckBox.isSelected()) {
shuttle.setCache(true);
shuttle.setCacheHint(CacheHint.SPEED);
} else {
shuttle.setCache(false);
// shuttle.setCacheHint(null);
}
field.setRotate(rotationComboBox.getValue());
timeline =
new Timeline(new KeyFrame(Duration.millis(Double.valueOf(durationField.getText())),
new KeyValue(shuttle.translateXProperty(), 370),
new KeyValue(shuttle.cacheHintProperty(), CacheHint.SPEED)));
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.setAutoReverse(true);
timeline.play();
}
private void stopAnimation()
{
timeline.stop();
disableSwitches(false);
shuttle.setTranslateX(0);
}
private Region shuttle;
private Timeline timeline;
private CheckBox scanCheckBox;
private CheckBox cacheCheckBox;
private ComboBox<Double> rotationComboBox;
private AnchorPane field;
private TextField durationField;
@Override
public void start(Stage primaryStage)
{
try {
Insets padding = new Insets(4);
VBox root = new VBox();
HBox switches = new HBox();
switches.setPadding(padding);
VBox.setVgrow(switches, Priority.NEVER);
Label scanLabel = new Label("Scan");
scanLabel.setPadding(padding);
scanCheckBox = new CheckBox();
scanCheckBox.setIndeterminate(false);
scanCheckBox.setFocusTraversable(true);
scanCheckBox.setMouseTransparent(false);
scanCheckBox.setSelected(false);
switches.getChildren()
.addAll(scanLabel, scanCheckBox);
Label cacheLabel = new Label("Cache");
cacheLabel.setPadding(padding);
cacheCheckBox = new CheckBox();
cacheCheckBox.setIndeterminate(false);
cacheCheckBox.setFocusTraversable(true);
cacheCheckBox.setMouseTransparent(false);
cacheCheckBox.setSelected(false);
switches.getChildren()
.addAll(cacheLabel, cacheCheckBox);
Label rotationLabel = new Label("Rotation");
rotationLabel.setPadding(padding);
rotationComboBox = new ComboBox<Double>();
rotationComboBox.setFocusTraversable(true);
rotationComboBox.setMouseTransparent(false);
rotationComboBox.getItems()
.addAll(Double.valueOf(0), Double.valueOf(89), Double.valueOf(90));
rotationComboBox.setValue(Double.valueOf(0));
HBox.setHgrow(rotationComboBox, Priority.NEVER);
switches.getChildren()
.addAll(rotationLabel, rotationComboBox);
Label durationLabel = new Label("Duration(ms)");
durationLabel.setPadding(padding);
durationField = new TextField("1000");
durationField.setFocusTraversable(true);
durationField.setMouseTransparent(false);
durationField.setPrefWidth(60);
HBox.setHgrow(durationField, Priority.NEVER);
switches.getChildren()
.addAll(durationLabel, durationField);
field = new AnchorPane();
VBox.setVgrow(field, Priority.ALWAYS);
shuttle = new Region();
shuttle.setPrefHeight(20);
shuttle.setPrefWidth(20);
shuttle.setStyle("-fx-background-color: black;");
field.getChildren()
.add(shuttle);
shuttle.relocate(10, 210);
root.getChildren()
.addAll(switches, field);
configureSwitchHandlers();
Scene scene = new Scene(root, 400, 433);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
private void configureSwitchHandlers()
{
scanCheckBox.setOnAction((event) -> {
if (scanCheckBox.isSelected()) {
// The box has just been turned 'on'
startAnimation();
} else {
// The box has just been turned 'off'
stopAnimation();
}
event.consume();
});
}
private void disableSwitches(boolean flag)
{
cacheCheckBox.setDisable(flag);
rotationComboBox.setDisable(flag);
durationField.setDisable(flag);
}
public static void main(String[] args)
{
launch(args);
}
}
package application;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.CacheHint;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application
{
// The meat of the problem is here ...
// If we choose a combination of setCache(true) and a 90 degree rotation (or multiple thereof) the image disappears
private void startAnimation()
{
disableSwitches(true);
if (cacheCheckBox.isSelected()) {
shuttle.setCache(true);
shuttle.setCacheHint(CacheHint.SPEED);
} else {
shuttle.setCache(false);
// shuttle.setCacheHint(null);
}
field.setRotate(rotationComboBox.getValue());
timeline =
new Timeline(new KeyFrame(Duration.millis(Double.valueOf(durationField.getText())),
new KeyValue(shuttle.translateXProperty(), 370),
new KeyValue(shuttle.cacheHintProperty(), CacheHint.SPEED)));
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.setAutoReverse(true);
timeline.play();
}
private void stopAnimation()
{
timeline.stop();
disableSwitches(false);
shuttle.setTranslateX(0);
}
private Region shuttle;
private Timeline timeline;
private CheckBox scanCheckBox;
private CheckBox cacheCheckBox;
private ComboBox<Double> rotationComboBox;
private AnchorPane field;
private TextField durationField;
@Override
public void start(Stage primaryStage)
{
try {
Insets padding = new Insets(4);
VBox root = new VBox();
HBox switches = new HBox();
switches.setPadding(padding);
VBox.setVgrow(switches, Priority.NEVER);
Label scanLabel = new Label("Scan");
scanLabel.setPadding(padding);
scanCheckBox = new CheckBox();
scanCheckBox.setIndeterminate(false);
scanCheckBox.setFocusTraversable(true);
scanCheckBox.setMouseTransparent(false);
scanCheckBox.setSelected(false);
switches.getChildren()
.addAll(scanLabel, scanCheckBox);
Label cacheLabel = new Label("Cache");
cacheLabel.setPadding(padding);
cacheCheckBox = new CheckBox();
cacheCheckBox.setIndeterminate(false);
cacheCheckBox.setFocusTraversable(true);
cacheCheckBox.setMouseTransparent(false);
cacheCheckBox.setSelected(false);
switches.getChildren()
.addAll(cacheLabel, cacheCheckBox);
Label rotationLabel = new Label("Rotation");
rotationLabel.setPadding(padding);
rotationComboBox = new ComboBox<Double>();
rotationComboBox.setFocusTraversable(true);
rotationComboBox.setMouseTransparent(false);
rotationComboBox.getItems()
.addAll(Double.valueOf(0), Double.valueOf(89), Double.valueOf(90));
rotationComboBox.setValue(Double.valueOf(0));
HBox.setHgrow(rotationComboBox, Priority.NEVER);
switches.getChildren()
.addAll(rotationLabel, rotationComboBox);
Label durationLabel = new Label("Duration(ms)");
durationLabel.setPadding(padding);
durationField = new TextField("1000");
durationField.setFocusTraversable(true);
durationField.setMouseTransparent(false);
durationField.setPrefWidth(60);
HBox.setHgrow(durationField, Priority.NEVER);
switches.getChildren()
.addAll(durationLabel, durationField);
field = new AnchorPane();
VBox.setVgrow(field, Priority.ALWAYS);
shuttle = new Region();
shuttle.setPrefHeight(20);
shuttle.setPrefWidth(20);
shuttle.setStyle("-fx-background-color: black;");
field.getChildren()
.add(shuttle);
shuttle.relocate(10, 210);
root.getChildren()
.addAll(switches, field);
configureSwitchHandlers();
Scene scene = new Scene(root, 400, 433);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
private void configureSwitchHandlers()
{
scanCheckBox.setOnAction((event) -> {
if (scanCheckBox.isSelected()) {
// The box has just been turned 'on'
startAnimation();
} else {
// The box has just been turned 'off'
stopAnimation();
}
event.consume();
});
}
private void disableSwitches(boolean flag)
{
cacheCheckBox.setDisable(flag);
rotationComboBox.setDisable(flag);
durationField.setDisable(flag);
}
public static void main(String[] args)
{
launch(args);
}
}
- relates to
-
JDK-8179946 Objects are not rendered for certain rotation angle and cache hint combinations
-
- Resolved
-