JavaFX FadeTransition, warten bis beendet

MarkusM

Aktives Mitglied
Hallo zusammen,

ich habe mal eine kurze Frage zum Thema "FadeTransition". Und zwar möchte ich gerne ein Pane ausblenden, ein neues Pane laden und dieses dann einblenden.

Ich habe allerdings das Problem, dass das Ausblenden noch läuft, während der Rest abgearbeitet wird.

Java:
    public void loadAnchorPane(AnchorPane ap){
        try {
            JavaFXEffects.fadeOut(ap);
            AnchorPane p = FXMLLoader.load(getClass().getResource("/sample/pane.fxml"));
            ap.getChildren().setAll(p);
            JavaFXEffects.fadeIn(ap);
        } catch (IOException e) {
        }
    }

Java:
public class JavaFXEffects {
    public static void fadeIn(Node node) {
        FadeTransition ft = new FadeTransition(Duration.millis(5000), node);
        ft.setFromValue(0.0);
        ft.setToValue(1.0);
        ft.play();
    }

    public static void fadeOut(Node node) {
        FadeTransition ft = new FadeTransition(Duration.millis(5000), node);
        ft.setFromValue(1.0);
        ft.setToValue(0.0);
        ft.play();
    }
}
 
Du kannst eine Property benutzten, welche du durch eine schnöde Timeline von 0 - 1 und dann wieder von 1 - 0 laufen lässt. Beide als eigenes KeyFrame.
Java:
//...
DoubleProperty opacity = new SimpleDoubleProperty(0);
node.opacityProperty.bind(opacity);
int timestep = 5000;
///...
Timeline timeline = new Timeline(
new KeyFrame(Duration.millis(timestep), new KeyValue(opacity,1)),
new KeyFrame(Duration.millis(timestep * 2), new KeyValue(opacity,0)));
timeline.play();
 
Bei mir im Code gibt es die opacityProperty() ebenfalls.
Du kannst übrigens auch mit ParellelTransitions oder SequentialTransition mehrere Transitions ausführen lassen... Hab ich jedenfalls so gemacht.
 
Sorry, ich hatte dicke Finger... 😕

Mein Problem bleibt aber trotzdem bestehen. Das Ausblenden wird irgendwie "übersprungen".

Ich hätte gern folgenden Ablauf:

AnchorPane ausblenden
neues AnchorPane setzen
AnchorPane einblenden
 
@dizm: Hast Du vielleicht mal ein Codebeispiel dafür, wie ich den "AnchorPane" setzen vernünftig zwischendie Transition bekomme?
 
Nö. Weil ich keine AnchorPanes verwende. Aber dafür ein StackPane, auf das ich alles drauf tu:

Java:
    private void toggleCenter(final Pane pane) {
        if (currentActiveNode != null) {
            currentActiveNode.setDisable(true);
            FadeTransition ft = new FadeTransition(Duration.millis(125), currentActiveNode);
            ft.setAutoReverse(false);
            ft.setFromValue(1.0);
            ft.setToValue(0.0);
            ft.setOnFinished(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    stackPaneContainer.getChildren().remove(currentActiveNode);
                    setCenter(pane);
                }
            });
            ft.play();
        } else {
            setCenter(pane);
        }
    }

    private void setCenter(final Pane pane) {
        if (pane != null && !stackPaneContainer.getChildren().contains(pane)) {
            stackPaneContainer.getChildren().add(pane);
            currentActiveNode = pane;
            currentActiveNode.setDisable(true);
            FadeTransition ft = new FadeTransition(Duration.millis(125), currentActiveNode);
            ft.setAutoReverse(false);
            ft.setFromValue(0.0);
            ft.setToValue(1.0);
            ft.setOnFinished(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    currentActiveNode.setDisable(false);
                }
            });
            ft.play();
        }
    }

Nicht unbedingt elegant, würde es heute vielleicht anders machen, aber es funktioniert recht zuverlässig und mit #toggleCenter(Pane) wird immer der Node nach vorne geholt und sichtbar gemacht, den ich sehen möchte.
 
Du kannst auch mit setOnFinished() auf das Beenden der vorherigen Transition reagieren. Dort kannst du das Pane wechseln und anschließend eine neue Transition starten.

Edit: da hatte jemand eine ähnliche Idee, schneller 🙂
Es geht auch mit lambda und dann ein wenig kürzer
Java:
setOnFinished(e -> {
    // do something
});
 
Lieben Dank,

ich habe das Ganze jetzt wie folgt gelöst:

Java:
    public void loadAnchorPane(final Pane ap, final String newFxmlName, final String oldFxmlName) {
        if (!newFxmlName.equals(oldFxmlName)) {
            final double duration = 200;
            FadeTransition ft = new FadeTransition(Duration.millis(duration), ap);
            ft.setFromValue(1.0);
            ft.setToValue(0.0);
            ft.setOnFinished(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    try {
                        AnchorPane p = FXMLLoader.load(getClass().getResource("/sample/" + newFxmlName));
                        ap.getChildren().setAll(p);
                        FadeTransition ft = new FadeTransition(Duration.millis(duration), ap);
                        ft.setFromValue(0.0);
                        ft.setToValue(1.0);
                        ft.play();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
            ft.play();
        }
    }
 
Ja, ich würde auch Lamdas - oder gar Methoden-Referenzen - präferieren, aber leider muss der gezeigte Code nosch auf Java7 lauffähig sein... 😕
 

Neue Themen


Zurück
Oben