1

I've recently started playing around with JavaFX :) I'm working on a little pet project and one of the issues I'm currently having is animating the resize of a VBox when a child is added or removed to/from the VBox.

I've got "the kids" fading out and then being removed from the VBox already. Once that animation completes I need the VBox height to resize preferably as an animation and not like the instant change it currently does.

The other threads that I've found are similar but I think they aren't quite exactly what I'm looking for.
Animation upon layout changes
Adding Node's animated to a VBox

Main Class:

package application;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCombination;
import javafx.scene.paint.Color;
import application.notifier.*;

public class Main extends Application
{
    @Override
    public void start(Stage stage)
    {
        try
        {
            stage.setTitle("Test");
            Group root = new Group();
            Scene scene = new Scene(root, (Screen.getPrimary().getBounds().getWidth()-100), (Screen.getPrimary().getBounds().getHeight()-100), Color.WHITE);

            Notifier notice = new Notifier();

            Notifier.addNotice("Testing Add Notice");
            Notifier.addNotice("Testing Add Notice again!");

            root.getChildren().add(Notifier.container);

            stage.setFullScreen(true);
            stage.setScene(scene);
            stage.setFullScreenExitHint("");
            //stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
            stage.show();

            Button test = new Button("Remove");
            test.setLayoutX(500.0);
            test.setLayoutY(500.0);

            test.setOnAction(new EventHandler<ActionEvent>() {
                @Override public void handle(ActionEvent e) {
                Notifier.removeNotice();
            }
            });

            root.getChildren().add(test);


        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        launch(args);
    }
}

Notifier Class:

import java.util.ArrayList;

import javafx.animation.FadeTransition;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Screen;
import javafx.util.Duration;

public class Notifier
{
    private static int maxVisibleNotices = 5;
    private static int currentVisible = 0;

    private static ArrayList<String> msgOverflow;

    public static VBox container;

    public Notifier()
    {
        BackgroundFill bkgrndFill = new BackgroundFill(Color.rgb(0, 0, 0, .65), new CornerRadii(10.0), new Insets(0));
        Background bkgrnd = new Background(bkgrndFill);

        Notifier.container = new VBox();
        Notifier.container.backgroundProperty().set(bkgrnd);
        Notifier.container.setAlignment(Pos.TOP_CENTER);
        Notifier.container.setMinWidth(Screen.getPrimary().getBounds().getWidth() - 50);
        Notifier.container.setMaxWidth(Screen.getPrimary().getBounds().getWidth() - 50);
        Notifier.container.setLayoutX((Screen.getPrimary().getBounds().getWidth() - (Screen.getPrimary().getBounds().getWidth() - 50))/2);
        Notifier.container.setLayoutY(5.0);
        Notifier.container.setSpacing(5.0);
        Notifier.container.setPadding(new Insets(5.0));

        Notifier.msgOverflow = new ArrayList<String>();
    }

    public static void addNotice(String msg)
    {
        if(Notifier.currentVisible < Notifier.maxVisibleNotices)
        {
            Text txt = new Text(msg);
            txt.setFill(Color.rgb(255,255,255));

            Notifier.container.getChildren().add(txt);
            Notifier.currentVisible++;
        }
        else
        {
            Notifier.msgOverflow.add(msg);
        }
    }

    public static void removeNotice()
    {
        if(Notifier.currentVisible > 0)
        {
            FadeTransition ft = new FadeTransition(Duration.millis(1000), Notifier.container.getChildren().get(0));
            ft.setFromValue(1.0);
            ft.setToValue(0.0);
            ft.setCycleCount(0);
            ft.setAutoReverse(false);
            ft.play();

            ft.setOnFinished(new EventHandler<ActionEvent>() {
                @Override public void handle(ActionEvent e) {
                    Notifier.container.getChildren().remove(0);
                    Notifier.currentVisible--;
                }
            });     
        }
    }
}

I hope this is clear enough. And thanks in advance for help or suggestions.

Community
  • 1
  • 1

1 Answers1

1

Probably not very helpful any more. I am currently working on the same thing.
You just need:
1. Add the same animation(if they all supposed to be same) to each of the remaining children in the VBox.
2. Use ParallelAnimation to make them run at the same time.
3. Use again a SequentialAnimation for you "kids" fading out animation and the parallel animation. This ensures they will not happen concurrently since multiple threads could run simultaneously.
4. To reach still the same view as what the instant update does, use animation/timeline.setonFinished(EventHandler()) to updates the screen

Jiao
  • 53
  • 5