{"id":54,"date":"2013-03-11T20:30:08","date_gmt":"2013-03-11T19:30:08","guid":{"rendered":"http:\/\/www.jensd.de\/wordpress\/?p=54"},"modified":"2014-10-23T15:06:15","modified_gmt":"2014-10-23T13:06:15","slug":"custom-component-starter","status":"publish","type":"post","link":"https:\/\/www.jensd.de\/wordpress\/?p=54","title":{"rendered":"Custom Component: Starter with hover effect"},"content":{"rendered":"<p>I was looking for a starter component for to use on the dock like main entry page of our application. It should have a hover effect on mouse enter\/ mouse exit and a start effect on mouse click.<\/p>\n<p>As JavaFX has already very useful <code>Transition<\/code> implementations I gave the <code>ScaleTransition<\/code> a try. I wanted a smooth expand and shrink effect on mouse enter and exit. Unfortunately transitions can on be played backwards. Reverse play is only supported when using the auto reverse option combined with an appropriate cycle count.<\/p>\n<p>But I saw that changing the properties of an existing <code>ScaleTransition<\/code> instance and <code>playFromStart()<\/code> is a working approach:<\/p>\n<p>[java]<br \/>\n        setOnMouseEntered(new EventHandler()<br \/>\n        {<br \/>\n            @Override<br \/>\n            public void handle(MouseEvent t)<br \/>\n            {<br \/>\n                scaleTransition.setFromX(getScaleX());<br \/>\n                scaleTransition.setFromY(getScaleY());<br \/>\n                scaleTransition.setToX(expandToMaxProperty.get());<br \/>\n                scaleTransition.setToY(expandToMaxProperty.get());<br \/>\n                scaleTransition.playFromStart();<br \/>\n            }<br \/>\n        });<\/p>\n<p>        setOnMouseExited(new EventHandler()<br \/>\n        {<br \/>\n            @Override<br \/>\n            public void handle(MouseEvent t)<br \/>\n            {<br \/>\n                scaleTransition.setFromX(getScaleX());<br \/>\n                scaleTransition.setFromY(getScaleY());<br \/>\n                scaleTransition.setToX(1);<br \/>\n                scaleTransition.setToY(1);<br \/>\n                scaleTransition.playFromStart();<br \/>\n            }<br \/>\n        });<br \/>\n[\/java]<\/p>\n<p>The start effect played on mouse click is a combination of both sequential and parallel played transitions: <strong>scale<\/strong> and <strong>fade out<\/strong> are played in parallel and in the end the starter goes back to an initial position:<\/p>\n<p>[java]<br \/>\n        fadeTransition = new FadeTransition(Duration.millis(200), this);<br \/>\n        fadeTransition.setCycleCount(1);<br \/>\n        fadeTransition<br \/>\n                .setInterpolator(Interpolator.EASE_BOTH);<\/p>\n<p>        startTransition = new ParallelTransition();<br \/>\n        startTransition.setCycleCount(2);<br \/>\n        startTransition.setAutoReverse(true);<br \/>\n        startTransition.getChildren()<br \/>\n                .addAll(scaleTransition,<br \/>\n                fadeTransition);<\/p>\n<p>        initTransition = new ScaleTransition(Duration.millis(200), this);<br \/>\n        initTransition.setToX(1);<br \/>\n        initTransition.setToY(1);<br \/>\n        initTransition.setCycleCount(1);<br \/>\n        initTransition<br \/>\n                .setInterpolator(Interpolator.EASE_BOTH);<\/p>\n<p>        startsSequentialTransition = new SequentialTransition();<br \/>\n        startsSequentialTransition.getChildren()<br \/>\n                .addAll(<br \/>\n                startTransition,<br \/>\n                initTransition);<br \/>\n[\/java]<\/p>\n<p><iframe loading=\"lazy\" title=\"JavaFX: Starter Demo1\" width=\"900\" height=\"675\" src=\"https:\/\/www.youtube.com\/embed\/vzqT09Xo79g?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen><\/iframe><\/p>\n<p><iframe loading=\"lazy\" title=\"JavaFX: Starter Demo2\" width=\"900\" height=\"675\" src=\"https:\/\/www.youtube.com\/embed\/xXyBYpYj_Ak?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen><\/iframe><\/p>\n<p>Whole Starter code<\/p>\n<p>[java]<br \/>\npublic class Starter extends StackPane<br \/>\n{<\/p>\n<p>    private ParallelTransition startTransition;<br \/>\n    private ScaleTransition scaleTransition;<br \/>\n    private ScaleTransition initTransition;<br \/>\n    private FadeTransition fadeTransition;<br \/>\n    private SequentialTransition startsSequentialTransition;<br \/>\n    private DoubleProperty expandToMaxProperty;<br \/>\n    private ImageView baseImage;<\/p>\n<p>    public Starter(String base, double fitWidth, double fitHeight)<br \/>\n    {<br \/>\n        baseImage = new ImageView(base);<br \/>\n        init(fitWidth, fitHeight);<br \/>\n    }<\/p>\n<p>    public Starter(Image base, double fitWidth, double fitHeight)<br \/>\n    {<br \/>\n        baseImage = new ImageView(base);<br \/>\n        init(fitWidth, fitHeight);<br \/>\n    }<\/p>\n<p>    private void init(double fitWidth, double fitHeight)<br \/>\n    {<br \/>\n        expandToMaxProperty = new SimpleDoubleProperty(1.2);<\/p>\n<p>        baseImage.setFitWidth(fitWidth);<br \/>\n        baseImage.setFitHeight(fitHeight);<\/p>\n<p>        Color selectedColor = Color.rgb(0, 0, 0, 0.5);<br \/>\n        DropShadow dropShadow = DropShadowBuilder.create()<br \/>\n                .color(selectedColor)<br \/>\n                .build();<br \/>\n        setEffect(dropShadow);<\/p>\n<p>        dropShadow.radiusProperty()<br \/>\n                .bind(scaleXProperty()<br \/>\n                .multiply(8));<br \/>\n        dropShadow.offsetXProperty()<br \/>\n                .bind(scaleXProperty()<br \/>\n                .multiply(8));<br \/>\n        dropShadow.offsetYProperty()<br \/>\n                .bind(scaleYProperty()<br \/>\n                .multiply(8));<\/p>\n<p>        scaleTransition =<br \/>\n                new ScaleTransition(Duration.millis(200), this);<br \/>\n        scaleTransition.setCycleCount(1);<br \/>\n        scaleTransition<br \/>\n                .setInterpolator(Interpolator.EASE_BOTH);<\/p>\n<p>        fadeTransition = new FadeTransition(Duration.millis(200), this);<br \/>\n        fadeTransition.setCycleCount(1);<br \/>\n        fadeTransition<br \/>\n                .setInterpolator(Interpolator.EASE_BOTH);<\/p>\n<p>        startTransition = new ParallelTransition();<br \/>\n        startTransition.setCycleCount(2);<br \/>\n        startTransition.setAutoReverse(true);<br \/>\n        startTransition.getChildren()<br \/>\n                .addAll(scaleTransition,<br \/>\n                fadeTransition);<\/p>\n<p>        initTransition =<br \/>\n                new ScaleTransition(Duration.millis(200), this);<br \/>\n        initTransition.setToX(1);<br \/>\n        initTransition.setToY(1);<br \/>\n        initTransition.setCycleCount(1);<br \/>\n        initTransition<br \/>\n                .setInterpolator(Interpolator.EASE_BOTH);<\/p>\n<p>        startsSequentialTransition = new SequentialTransition();<br \/>\n        startsSequentialTransition.getChildren()<br \/>\n                .addAll(<br \/>\n                startTransition,<br \/>\n                initTransition);<\/p>\n<p>        getChildren()<br \/>\n                .addAll(baseImage);<\/p>\n<p>        setOnMouseEntered(new EventHandler<MouseEvent>()<br \/>\n        {<br \/>\n            @Override<br \/>\n            public void handle(MouseEvent t)<br \/>\n            {<br \/>\n                scaleTransition.setFromX(getScaleX());<br \/>\n                scaleTransition.setFromY(getScaleY());<br \/>\n                scaleTransition.setToX(expandToMaxProperty.get());<br \/>\n                scaleTransition.setToY(expandToMaxProperty.get());<br \/>\n                scaleTransition.playFromStart();<br \/>\n            }<br \/>\n        });<\/p>\n<p>        setOnMouseExited(new EventHandler<MouseEvent>()<br \/>\n        {<br \/>\n            @Override<br \/>\n            public void handle(MouseEvent t)<br \/>\n            {<br \/>\n                scaleTransition.setFromX(getScaleX());<br \/>\n                scaleTransition.setFromY(getScaleY());<br \/>\n                scaleTransition.setToX(1);<br \/>\n                scaleTransition.setToY(1);<br \/>\n                scaleTransition.playFromStart();<br \/>\n            }<br \/>\n        });<\/p>\n<p>        setOnMouseClicked(new EventHandler<MouseEvent>()<br \/>\n        {<br \/>\n            @Override<br \/>\n            public void handle(MouseEvent t)<br \/>\n            {<br \/>\n                scaleTransition.setFromX(getScaleX());<br \/>\n                scaleTransition.setFromY(getScaleY());<br \/>\n                scaleTransition.setToX(2);<br \/>\n                scaleTransition.setToY(2);<br \/>\n                fadeTransition.setFromValue(1.0f);<br \/>\n                fadeTransition.setToValue(0.5f);<br \/>\n                startsSequentialTransition.playFromStart();<br \/>\n            }<br \/>\n        });<br \/>\n    }<\/p>\n<p>    public DoubleProperty expandToMaxProperty()<br \/>\n    {<br \/>\n        return expandToMaxProperty;<br \/>\n    }<br \/>\n}<br \/>\n[\/java]<\/p>\n<p><strong>[ U P D A T E      21-10-2014]<\/strong><\/p>\n<p>Made some modifications to get the Starter running on Java 8:<\/p>\n<p>[java]<br \/>\npublic class Starter extends StackPane<br \/>\n{<\/p>\n<p>    private ParallelTransition startTransition;<br \/>\n    private ScaleTransition scaleTransition;<br \/>\n    private ScaleTransition startScaleTransition;<br \/>\n    private ScaleTransition initTransition;<br \/>\n    private FadeTransition fadeTransition;<br \/>\n    private SequentialTransition startsSequentialTransition;<br \/>\n    private DoubleProperty expandToMaxProperty;<br \/>\n    private final ImageView baseImage;<\/p>\n<p>    public Starter(String base, double fitWidth, double fitHeight)<br \/>\n    {<br \/>\n        baseImage = new ImageView(base);<br \/>\n        init(fitWidth, fitHeight);<br \/>\n    }<\/p>\n<p>    public Starter(Image base, double fitWidth, double fitHeight)<br \/>\n    {<br \/>\n        baseImage = new ImageView(base);<br \/>\n        init(fitWidth, fitHeight);<br \/>\n    }<\/p>\n<p>    private void init(double fitWidth, double fitHeight)<br \/>\n    {<br \/>\n        expandToMaxProperty = new SimpleDoubleProperty(1.2);<\/p>\n<p>        baseImage.setFitWidth(fitWidth);<br \/>\n        baseImage.setFitHeight(fitHeight);<\/p>\n<p>        Color selectedColor = Color.rgb(0, 0, 0, 0.5);<br \/>\n        DropShadow dropShadow = DropShadowBuilder.create()<br \/>\n                .color(selectedColor)<br \/>\n                .build();<br \/>\n        setEffect(dropShadow);<\/p>\n<p>        dropShadow.radiusProperty()<br \/>\n                .bind(scaleXProperty()<br \/>\n                .multiply(8));<br \/>\n        dropShadow.offsetXProperty()<br \/>\n                .bind(scaleXProperty()<br \/>\n                .multiply(8));<br \/>\n        dropShadow.offsetYProperty()<br \/>\n                .bind(scaleYProperty()<br \/>\n                .multiply(8));<\/p>\n<p>        scaleTransition =<br \/>\n                new ScaleTransition(Duration.millis(200), this);<br \/>\n        scaleTransition.setCycleCount(1);<br \/>\n        scaleTransition<br \/>\n                .setInterpolator(Interpolator.EASE_BOTH);<\/p>\n<p>        startScaleTransition =<br \/>\n                new ScaleTransition(Duration.millis(200), this);<br \/>\n        startScaleTransition.setCycleCount(1);<br \/>\n        startScaleTransition<br \/>\n                .setInterpolator(Interpolator.EASE_BOTH);<\/p>\n<p>        fadeTransition = new FadeTransition(Duration.millis(200), this);<br \/>\n        fadeTransition.setCycleCount(1);<br \/>\n        fadeTransition<br \/>\n                .setInterpolator(Interpolator.EASE_BOTH);<\/p>\n<p>        startTransition = new ParallelTransition();<br \/>\n        startTransition.setCycleCount(2);<br \/>\n        startTransition.setAutoReverse(true);<br \/>\n        startTransition.getChildren()<br \/>\n                .addAll(startScaleTransition, fadeTransition);<\/p>\n<p>        initTransition =<br \/>\n                new ScaleTransition(Duration.millis(200), this);<br \/>\n        initTransition.setToX(1);<br \/>\n        initTransition.setToY(1);<br \/>\n        initTransition.setCycleCount(1);<br \/>\n        initTransition<br \/>\n                .setInterpolator(Interpolator.EASE_BOTH);<\/p>\n<p>        startsSequentialTransition = new SequentialTransition();<br \/>\n        startsSequentialTransition.getChildren()<br \/>\n                .addAll(<br \/>\n                startTransition,<br \/>\n                initTransition);<\/p>\n<p>        getChildren()<br \/>\n                .addAll(baseImage);<\/p>\n<p>        setOnMouseEntered((MouseEvent t) -> {<br \/>\n            scaleTransition.setFromX(getScaleX());<br \/>\n            scaleTransition.setFromY(getScaleY());<br \/>\n            scaleTransition.setToX(expandToMaxProperty.get());<br \/>\n            scaleTransition.setToY(expandToMaxProperty.get());<br \/>\n            scaleTransition.playFromStart();<br \/>\n        });<\/p>\n<p>        setOnMouseExited((MouseEvent t) -> {<br \/>\n            scaleTransition.setFromX(getScaleX());<br \/>\n            scaleTransition.setFromY(getScaleY());<br \/>\n            scaleTransition.setToX(1);<br \/>\n            scaleTransition.setToY(1);<br \/>\n            scaleTransition.playFromStart();<br \/>\n        });<\/p>\n<p>        setOnMouseClicked((MouseEvent t) -> {<br \/>\n            startScaleTransition.setFromX(getScaleX());<br \/>\n            startScaleTransition.setFromY(getScaleY());<br \/>\n            startScaleTransition.setToX(2);<br \/>\n            startScaleTransition.setToY(2);<br \/>\n            fadeTransition.setFromValue(1.0f);<br \/>\n            fadeTransition.setToValue(0.5f);<br \/>\n            startsSequentialTransition.playFromStart();<br \/>\n        });<br \/>\n    }<\/p>\n<p>    public DoubleProperty expandToMaxProperty()<br \/>\n    {<br \/>\n        return expandToMaxProperty;<br \/>\n    }<br \/>\n}<br \/>\n[\/java]<\/p>\n<p>Find complete code repo at <a href=\"https:\/\/bitbucket.org\/Jerady\/springboard\" title=\"https:\/\/bitbucket.org\/Jerady\/springboard\" target=\"_blank\">BitBucket<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was looking for a starter component for to use on the dock like main entry page of our application. It should have a hover effect on mouse enter\/ mouse exit and a start effect on mouse click. As JavaFX has already very useful Transition implementations I gave the ScaleTransition a try. I wanted a&hellip; <span class=\"clear\"><\/span><a href=\"https:\/\/www.jensd.de\/wordpress\/?p=54\" class=\"more-link read-more\" rel=\"bookmark\">Continue Reading <span class=\"screen-reader-text\">Custom Component: Starter with hover effect<\/span><i class=\"fa fa-arrow-right\"><\/i><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"footnotes":"","_jetpack_memberships_contains_paid_content":false,"jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[12,9,4,13],"tags":[],"jetpack_publicize_connections":[],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p38FCL-S","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.jensd.de\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/54"}],"collection":[{"href":"https:\/\/www.jensd.de\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jensd.de\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jensd.de\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jensd.de\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=54"}],"version-history":[{"count":62,"href":"https:\/\/www.jensd.de\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/54\/revisions"}],"predecessor-version":[{"id":1647,"href":"https:\/\/www.jensd.de\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/54\/revisions\/1647"}],"wp:attachment":[{"href":"https:\/\/www.jensd.de\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=54"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jensd.de\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=54"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jensd.de\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=54"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}