How to get rid of focus highlighting in JavaFX

Today I was asked if I know a way to get rid of the focus-highlighting of JavaFX controls (respectively buttons):

button_hover

Most posts and tipps regarding this issue suggesting to adding:

.button:focused {
    -fx-focus-color: transparent; 
}

But with this style a glow like this is still left:

button_glow

To get rid of this glow also often suggested to play around with -fx-background-insets additionally:

.button:focused {
    -fx-focus-color: transparent; 
    -fx-background-insets: -1.4, 0, 1, 2;
}

But this results in a button rendered with out an outer border:

button_insets

Compared to the default button style

button

this is still a kind of “highlighting”:

Why is that? (And why are there actually 4 inset values ?)
(note he comment of David Grieve below)

Having a look at the JavaFX default style as defined by modena.css bares some more information:

/* A bright blue for the focus indicator of objects. Typically used as the
* first color in -fx-background-color for the "focused" pseudo-class. Also
* typically used with insets of -1.4 to provide a glowing effect.
*/
-fx-focus-color: #f25f29;
-fx-faint-focus-color: #f25f2933;

Obviously there is not only one focus color -fx-focus-color but also -fx-faint-focus-color which is meant to create this glow-effect (that is remaining when setting -fx-focus-color:transparent;).

A closer look at the .button:focused pseudo class (in modena.css):

.button:focused {
    -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-inner-border, -fx-body-color; 
    -fx-background-insets: -2, -0.3, 1, 2;
    -fx-background-radius: 7, 6, 4, 3;
}

Playing around with some (extreme ;-)) colouring reveals the arrangement:

.button:focused {
    -fx-focus-color: red;
    -fx-faint-focus-color: green;
    -fx-inner-border: blue;
    -fx-body-color: orange;

    -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-inner-border, -fx-body-color; 
    -fx-background-insets: -2, -0.3, 1, 2;
    -fx-background-radius: 7, 6, 4, 3;
}

button_hover_style

Getting back to the topic maybe a clent way to remove the focus hightlight is to use the default button styles also for .button:focus (same approach for other controls):

.button:focused {
    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; 
    -fx-background-insets: 0, 1, 2;
    -fx-background-radius: 5, 4, 3;
}

Using ‘Font Awesome’ Icons with JavaFX

Refer for latest updates here.

Dave Gandy has created a incredible cool icon font called Font Awesome.

These font icons perfectly fit into JavaFX Apps as:

  • all these beautiful icons are scalable vector graphics
  • each icon (unicode character) can be styled with css
  • incredible lightweight (one font 249 icons)

Load the “Awesome Font”

Font.loadFont(App.class.getResource("/fonts/awesome.ttf").
            toExternalForm(), 12);

Assign Awesome Font by css
E.g. this is the “icons_blue.css” style:

.root{
  -icons-color: rgb(61,114,144);
}

.icons{
    -fx-font-family: FontAwesome;
    -fx-font-size: 16px;
    -fx-effect: innershadow( three-pass-box , derive(-icons-color,-70%) , 0.1em, 0.0 , 0.07em, 0.07em );
    -fx-text-fill: linear-gradient(to bottom, derive(-icons-color,20%) 10%, derive(-icons-color,-40%) 80%);
}

.icons:hover{
    -fx-effect: dropshadow( three-pass-box , derive(-icons-color,0%) , 0.01em, 0.0 , 0, 0);
}

Display the icon via its unicode character

The Font Awesome project contains a css file with a icon name / unicode character mapping:

....
/*  Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
    readers do not read off random characters that represent icons */
.icon-glass:before                { content: "\f000"; }
.icon-music:before                { content: "\f001"; }
.icon-search:before               { content: "\f002"; }
.icon-envelope:before             { content: "\f003"; }
.icon-heart:before                { content: "\f004"; }
.icon-star:before                 { content: "\f005"; }
.icon-star-empty:before           { content: "\f006"; }
.icon-user:before                 { content: "\f007"; }
.icon-film:before                 { content: "\f008"; }
.icon-th-large:before             { content: "\f009"; }
....

AwesomeIcons
For a convenient usage in Java I created a simple similar mapping class:

public class AwesomeIcons
{

    private AwesomeIcons()
    {
        /* not needed*/
    }
    public static final String ICON_GLASS = "\uf000";
    public static final String ICON_MUSIC = "\uf001";
    public static final String ICON_SEARCH = "\uf002";
    public static final String ICON_ENVELOPE = "\uf003";
    public static final String ICON_HEART = "\uf004";
    public static final String ICON_STAR = "\uf005";
    public static final String ICON_STAR_EMPTY = "\uf006";
    public static final String ICON_USER = "\uf007";
    public static final String ICON_FILM = "\uf008";
    public static final String ICON_TH_LARGE = "\uf009";
    public static final String ICON_TH = "\uf00a";
    public static final String ICON_TH_LIST = "\uf00b";
    public static final String ICON_OK = "\uf00c";
    public static final String ICON_REMOVE = "\uf00d";
    public static final String ICON_ZOOM_IN = "\uf00e";
    public static final String ICON_ZOOM_OUT = "\uf010";
    public static final String ICON_OFF = "\uf011";
    public static final String ICON_SIGNAL = "\uf012";
    public static final String ICON_COG = "\uf013";
    public static final String ICON_TRASH = "\uf014";
    public static final String ICON_HOME = "\uf015";
    public static final String ICON_FILE = "\uf016";
    public static final String ICON_TIME = "\uf017";
    public static final String ICON_ROAD = "\uf018";
    public static final String ICON_DOWNLOAD_ALT = "\uf019";
    public static final String ICON_DOWNLOAD = "\uf01a";
    public static final String ICON_UPLOAD = "\uf01b";
    public static final String ICON_INBOX = "\uf01c";
    public static final String ICON_PLAY_CIRCLE = "\uf01d";
    public static final String ICON_REPEAT = "\uf01e";
    public static final String ICON_REFRESH = "\uf021";
    public static final String ICON_LIST_ALT = "\uf022";
    public static final String ICON_LOCK = "\uf023";
    public static final String ICON_FLAG = "\uf024";
    public static final String ICON_HEADPHONES = "\uf025";
    public static final String ICON_VOLUME_OFF = "\uf026";
    public static final String ICON_VOLUME_DOWN = "\uf027";
    public static final String ICON_VOLUME_UP = "\uf028";
    public static final String ICON_QRCODE = "\uf029";
    public static final String ICON_BARCODE = "\uf02a";
    public static final String ICON_TAG = "\uf02b";
    public static final String ICON_TAGS = "\uf02c";
    public static final String ICON_BOOK = "\uf02d";
    public static final String ICON_BOOKMARK = "\uf02e";
    public static final String ICON_PRINT = "\uf02f";
    public static final String ICON_CAMERA = "\uf030";
    public static final String ICON_FONT = "\uf031";
    public static final String ICON_BOLD = "\uf032";
    public static final String ICON_ITALIC = "\uf033";
    public static final String ICON_TEXT_HEIGHT = "\uf034";
    public static final String ICON_TEXT_WIDTH = "\uf035";
    public static final String ICON_ALIGN_LEFT = "\uf036";
    public static final String ICON_ALIGN_CENTER = "\uf037";
    public static final String ICON_ALIGN_RIGHT = "\uf038";
    public static final String ICON_ALIGN_JUSTIFY = "\uf039";
    public static final String ICON_LIST = "\uf03a";
    public static final String ICON_INDENT_LEFT = "\uf03b";
    public static final String ICON_INDENT_RIGHT = "\uf03c";
    public static final String ICON_FACETIME_VIDEO = "\uf03d";
    public static final String ICON_PICTURE = "\uf03e";
    public static final String ICON_PENCIL = "\uf040";
    public static final String ICON_MAP_MARKER = "\uf041";
    public static final String ICON_ADJUST = "\uf042";
    public static final String ICON_TINT = "\uf043";
    public static final String ICON_EDIT = "\uf044";
    public static final String ICON_SHARE = "\uf045";
    public static final String ICON_CHECK = "\uf046";
    public static final String ICON_MOVE = "\uf047";
    public static final String ICON_STEP_BACKWARD = "\uf048";
    public static final String ICON_FAST_BACKWARD = "\uf049";
    public static final String ICON_BACKWARD = "\uf04a";
    public static final String ICON_PLAY = "\uf04b";
    public static final String ICON_PAUSE = "\uf04c";
    public static final String ICON_STOP = "\uf04d";
    public static final String ICON_FORWARD = "\uf04e";
    public static final String ICON_FAST_FORWARD = "\uf050";
    public static final String ICON_STEP_FORWARD = "\uf051";
    public static final String ICON_EJECT = "\uf052";
    public static final String ICON_CHEVRON_LEFT = "\uf053";
    public static final String ICON_CHEVRON_RIGHT = "\uf054";
    public static final String ICON_PLUS_SIGN = "\uf055";
    public static final String ICON_MINUS_SIGN = "\uf056";
    public static final String ICON_REMOVE_SIGN = "\uf057";
    public static final String ICON_OK_SIGN = "\uf058";
    public static final String ICON_QUESTION_SIGN = "\uf059";
    public static final String ICON_INFO_SIGN = "\uf05a";
    public static final String ICON_SCREENSHOT = "\uf05b";
    public static final String ICON_REMOVE_CIRCLE = "\uf05c";
    public static final String ICON_OK_CIRCLE = "\uf05d";
    public static final String ICON_BAN_CIRCLE = "\uf05e";
    public static final String ICON_ARROW_LEFT = "\uf060";
    public static final String ICON_ARROW_RIGHT = "\uf061";
    public static final String ICON_ARROW_UP = "\uf062";
    public static final String ICON_ARROW_DOWN = "\uf063";
    public static final String ICON_SHARE_ALT = "\uf064";
    public static final String ICON_RESIZE_FULL = "\uf065";
    public static final String ICON_RESIZE_SMALL = "\uf066";
    public static final String ICON_PLUS = "\uf067";
    public static final String ICON_MINUS = "\uf068";
    public static final String ICON_ASTERISK = "\uf069";
    public static final String ICON_EXCLAMATION_SIGN = "\uf06a";
    public static final String ICON_GIFT = "\uf06b";
    public static final String ICON_LEAF = "\uf06c";
    public static final String ICON_FIRE = "\uf06d";
    public static final String ICON_EYE_OPEN = "\uf06e";
    public static final String ICON_EYE_CLOSE = "\uf070";
    public static final String ICON_WARNING_SIGN = "\uf071";
    public static final String ICON_PLANE = "\uf072";
    public static final String ICON_CALENDAR = "\uf073";
    public static final String ICON_RANDOM = "\uf074";
    public static final String ICON_COMMENT = "\uf075";
    public static final String ICON_MAGNET = "\uf076";
    public static final String ICON_CHEVRON_UP = "\uf077";
    public static final String ICON_CHEVRON_DOWN = "\uf078";
    public static final String ICON_RETWEET = "\uf079";
    public static final String ICON_SHOPPING_CART = "\uf07a";
    public static final String ICON_FOLDER_CLOSE = "\uf07b";
    public static final String ICON_FOLDER_OPEN = "\uf07c";
    public static final String ICON_RESIZE_VERTICAL = "\uf07d";
    public static final String ICON_RESIZE_HORIZONTAL = "\uf07e";
    public static final String ICON_BAR_CHART = "\uf080";
    public static final String ICON_TWITTER_SIGN = "\uf081";
    public static final String ICON_FACEBOOK_SIGN = "\uf082";
    public static final String ICON_CAMERA_RETRO = "\uf083";
    public static final String ICON_KEY = "\uf084";
    public static final String ICON_COGS = "\uf085";
    public static final String ICON_COMMENTS = "\uf086";
    public static final String ICON_THUMBS_UP = "\uf087";
    public static final String ICON_THUMBS_DOWN = "\uf088";
    public static final String ICON_STAR_HALF = "\uf089";
    public static final String ICON_HEART_EMPTY = "\uf08a";
    public static final String ICON_SIGNOUT = "\uf08b";
    public static final String ICON_LINKEDIN_SIGN = "\uf08c";
    public static final String ICON_PUSHPIN = "\uf08d";
    public static final String ICON_EXTERNAL_LINK = "\uf08e";
    public static final String ICON_SIGNIN = "\uf090";
    public static final String ICON_TROPHY = "\uf091";
    public static final String ICON_GITHUB_SIGN = "\uf092";
    public static final String ICON_UPLOAD_ALT = "\uf093";
    public static final String ICON_LEMON = "\uf094";
    public static final String ICON_PHONE = "\uf095";
    public static final String ICON_CHECK_EMPTY = "\uf096";
    public static final String ICON_BOOKMARK_EMPTY = "\uf097";
    public static final String ICON_PHONE_SIGN = "\uf098";
    public static final String ICON_TWITTER = "\uf099";
    public static final String ICON_FACEBOOK = "\uf09a";
    public static final String ICON_GITHUB = "\uf09b";
    public static final String ICON_UNLOCK = "\uf09c";
    public static final String ICON_CREDIT_CARD = "\uf09d";
    public static final String ICON_RSS = "\uf09e";
    public static final String ICON_HDD = "\uf0a0";
    public static final String ICON_BULLHORN = "\uf0a1";
    public static final String ICON_BELL = "\uf0a2";
    public static final String ICON_CERTIFICATE = "\uf0a3";
    public static final String ICON_HAND_RIGHT = "\uf0a4";
    public static final String ICON_HAND_LEFT = "\uf0a5";
    public static final String ICON_HAND_UP = "\uf0a6";
    public static final String ICON_HAND_DOWN = "\uf0a7";
    public static final String ICON_CIRCLE_ARROW_LEFT = "\uf0a8";
    public static final String ICON_CIRCLE_ARROW_RIGHT = "\uf0a9";
    public static final String ICON_CIRCLE_ARROW_UP = "\uf0aa";
    public static final String ICON_CIRCLE_ARROW_DOWN = "\uf0ab";
    public static final String ICON_GLOBE = "\uf0ac";
    public static final String ICON_WRENCH = "\uf0ad";
    public static final String ICON_TASKS = "\uf0ae";
    public static final String ICON_FILTER = "\uf0b0";
    public static final String ICON_BRIEFCASE = "\uf0b1";
    public static final String ICON_FULLSCREEN = "\uf0b2";
    public static final String ICON_GROUP = "\uf0c0";
    public static final String ICON_LINK = "\uf0c1";
    public static final String ICON_CLOUD = "\uf0c2";
    public static final String ICON_BEAKER = "\uf0c3";
    public static final String ICON_CUT = "\uf0c4";
    public static final String ICON_COPY = "\uf0c5";
    public static final String ICON_PAPER_CLIP = "\uf0c6";
    public static final String ICON_SAVE = "\uf0c7";
    public static final String ICON_SIGN_BLANK = "\uf0c8";
    public static final String ICON_REORDER = "\uf0c9";
    public static final String ICON_LIST_UL = "\uf0ca";
    public static final String ICON_LIST_OL = "\uf0cb";
    public static final String ICON_STRIKETHROUGH = "\uf0cc";
    public static final String ICON_UNDERLINE = "\uf0cd";
    public static final String ICON_TABLE = "\uf0ce";
    public static final String ICON_MAGIC = "\uf0d0";
    public static final String ICON_TRUCK = "\uf0d1";
    public static final String ICON_PINTEREST = "\uf0d2";
    public static final String ICON_PINTEREST_SIGN = "\uf0d3";
    public static final String ICON_GOOGLE_PLUS_SIGN = "\uf0d4";
    public static final String ICON_GOOGLE_PLUS = "\uf0d5";
    public static final String ICON_MONEY = "\uf0d6";
    public static final String ICON_CARET_DOWN = "\uf0d7";
    public static final String ICON_CARET_UP = "\uf0d8";
    public static final String ICON_CARET_LEFT = "\uf0d9";
    public static final String ICON_CARET_RIGHT = "\uf0da";
    public static final String ICON_COLUMNS = "\uf0db";
    public static final String ICON_SORT = "\uf0dc";
    public static final String ICON_SORT_DOWN = "\uf0dd";
    public static final String ICON_SORT_UP = "\uf0de";
    public static final String ICON_ENVELOPE_ALT = "\uf0e0";
    public static final String ICON_LINKEDIN = "\uf0e1";
    public static final String ICON_UNDO = "\uf0e2";
    public static final String ICON_LEGAL = "\uf0e3";
    public static final String ICON_DASHBOARD = "\uf0e4";
    public static final String ICON_COMMENT_ALT = "\uf0e5";
    public static final String ICON_COMMENTS_ALT = "\uf0e6";
    public static final String ICON_BOLT = "\uf0e7";
    public static final String ICON_SITEMAP = "\uf0e8";
    public static final String ICON_UMBRELLA = "\uf0e9";
    public static final String ICON_PASTE = "\uf0ea";
    public static final String ICON_LIGHTBULB = "\uf0eb";
    public static final String ICON_EXCHANGE = "\uf0ec";
    public static final String ICON_CLOUD_DOWNLOAD = "\uf0ed";
    public static final String ICON_CLOUD_UPLOAD = "\uf0ee";
    public static final String ICON_USER_MD = "\uf0f0";
    public static final String ICON_STETHOSCOPE = "\uf0f1";
    public static final String ICON_SUITCASE = "\uf0f2";
    public static final String ICON_BELL_ALT = "\uf0f3";
    public static final String ICON_COFFEE = "\uf0f4";
    public static final String ICON_FOOD = "\uf0f5";
    public static final String ICON_FILE_ALT = "\uf0f6";
    public static final String ICON_BUILDING = "\uf0f7";
    public static final String ICON_HOSPITAL = "\uf0f8";
    public static final String ICON_AMBULANCE = "\uf0f9";
    public static final String ICON_MEDKIT = "\uf0fa";
    public static final String ICON_FIGHTER_JET = "\uf0fb";
    public static final String ICON_BEER = "\uf0fc";
    public static final String ICON_H_SIGN = "\uf0fd";
    public static final String ICON_PLUS_SIGN_ALT = "\uf0fe";
    public static final String ICON_DOUBLE_ANGLE_LEFT = "\uf100";
    public static final String ICON_DOUBLE_ANGLE_RIGHT = "\uf101";
    public static final String ICON_DOUBLE_ANGLE_UP = "\uf102";
    public static final String ICON_DOUBLE_ANGLE_DOWN = "\uf103";
    public static final String ICON_ANGLE_LEFT = "\uf104";
    public static final String ICON_ANGLE_RIGHT = "\uf105";
    public static final String ICON_ANGLE_UP = "\uf106";
    public static final String ICON_ANGLE_DOWN = "\uf107";
    public static final String ICON_DESKTOP = "\uf108";
    public static final String ICON_LAPTOP = "\uf109";
    public static final String ICON_TABLET = "\uf10a";
    public static final String ICON_MOBILE_PHONE = "\uf10b";
    public static final String ICON_CIRCLE_BLANK = "\uf10c";
    public static final String ICON_QUOTE_LEFT = "\uf10d";
    public static final String ICON_QUOTE_RIGHT = "\uf10e";
    public static final String ICON_SPINNER = "\uf110";
    public static final String ICON_CIRCLE = "\uf111";
    public static final String ICON_REPLY = "\uf112";
    public static final String ICON_GITHUB_ALT = "\uf113";
    public static final String ICON_FOLDER_CLOSE_ALT = "\uf114";
    public static final String ICON_FOLDER_OPEN_ALT = "\uf115";
}

AwesomeFactory

By now AwesomeFactory basically provides 2 method to create an icon Label and an icon Button:

Label pictureLabel = AwesomeDude
             .createIconLabel(AwesomeIcons.ICON_PICTURE, 32);

Button refreshButton = AwesomeDude
            .createIconButton(AwesomeIcons.ICON_REFRESH, "Refresh");

The default css style will be automatically assigned by these methods.
Other themes/styles can be set by overwriting the icons class.

An this is the AwesomeDude:

public class AwesomeDude
{

    public static Button createIconButton(String iconName)
    {
        return createIconButton(iconName, "", 16);
    }

    public static Button createIconButton(String iconName, String text)
    {
        return createIconButton(iconName, text, 16);
    }

    public static Button createIconButton(String iconName, int iconSize)
    {
        return createIconButton(iconName, "", iconSize);
    }

    public static Button createIconButton(String iconName, String text, int iconSize)
    {
        Label icon = createIconLabel(iconName);
        icon.setStyle("-fx-font-size: " + iconSize + "px;");
        return ButtonBuilder.create()
                .text(text)
                .graphic(icon)
                .build();
    }

    public static Label createIconLabel(String iconName, String style)
    {
        return LabelBuilder.create()
                .text(iconName)
                .style(style)
                .build();
    }

    public static Label createIconLabel(String iconName)
    {
        return createIconLabel(iconName, 16);
    }

    public static Label createIconLabel(String iconName, int iconSize)
    {
        return LabelBuilder.create()
                .text(iconName)
                .styleClass("icons")
                .style("-fx-font-size: " + iconSize + "px;")
                .build();
    }
}

First steps with JavaFX

This tutorial will introduce

  • Clean separation of application UI and logic
  • Using Builders supporting Fluent API
  • Effects
  • Layouts
  • Property Bindings
  • EventHandler

Abstract

The Golden Ratio (Golden MeanGolden Section) is defined as φ = (√5 + 1) / 2.

Objective

Create an UI to find the golden section by using a slider. Add value labels and an indicator to get green when golden action is hit.

The Model

Create observable double a and b values and a boolean value to indicate whether the golden section has been hit:

private DoubleProperty aValue = new SimpleDoubleProperty(0.0);
private DoubleProperty bValue = new SimpleDoubleProperty(0.0);
private BooleanProperty sectioAurea = new SimpleBooleanProperty(false);

Method to calculate the golden section:

private void reCalculate(){

double b = aValue.substract(100).multiply(-1).get();
setBValue(b);

double result1 = aValue.get()/bValue.get();
result1 = Math.round(result1*100.0)/100.0;

double result2 = (aValue.get()+bValue.get())/aValue.get();
result2 = Math.round(result2*100.0)/100.0;

sectioAurea.set(result1 == result2);
}

Please note: get() returns the primitive double value, getValue() respectively returns the Double instance.

Next attach listeners to re-caculate the golden section indicator on value changes:

private void attachListener(){ChangeListener onChangeListener = new ChangeListener(){
@Override
public void changed(ObservableValue arg0, Number arg1, Number arg2) {
reCalculate();
}
};

getAValueProperty().addListener(onChangeListener);
getBValueProperty().addListener(onChangeListener);
}

Here is the complete model code width appropriate getter and setter methods:

package de.jensd.javafx.aurea;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;

/**
*
* @author Jens Deters
*/
public class SectioModel {

private DoubleProperty aValue = new SimpleDoubleProperty(0.0);
private DoubleProperty bValue = new SimpleDoubleProperty(0.0);
private BooleanProperty sectioAurea = new SimpleBooleanProperty(false);

public SectioModel() {
attachListener();
}

private void attachListener(){

ChangeListener onChangeListener = new ChangeListener(){
@Override
public void changed(ObservableValue arg0, Number arg1, Number arg2) {
reCalculate();
}
};

getAValueProperty().addListener(onChangeListener);
getBValueProperty().addListener(onChangeListener);
}

public DoubleProperty getAValueProperty() {
return aValue;
}

public double getAValue() {
return aValue.get();
}

public void setAValue(double d) {
aValue.set(d);
}

public DoubleProperty getBValueProperty() {
return bValue;
}

public double getBValue() {
return bValue.get();
}

public void setBValue(double d) {
bValue.set(d);
}

public BooleanProperty getSectioAureaProperty() {
return sectioAurea;
}

public boolean isSectioAurea() {
return sectioAurea.get();
}

private void reCalculate(){

double b = aValue.substract(100).multiply(-1).get();
setBValue(b);

double result1 = aValue.get()/bValue.get();
result1 = Math.round(result1*100.0)/100.0;

double result2 = (aValue.get()+bValue.get())/aValue.get();
result2 = Math.round(result2*100.0)/100.0;

sectioAurea.set(result1 == result2);
}
}

The UI 

Title Label and usage hint

Text titleText = TextBuilder.create().
text("Sectio Aurea").
effect(ds).
font(Font.font(null, FontWeight.BOLD, 32)).
build();

Text descriptionText = TextBuilder.create().
text("Move the slider until your hit the golden section.\nHint: use the cursor keys for exact control.").
textAlignment(TextAlignment.CENTER).
build();

Indicator

Stop[] falseStops = new Stop[]{new Stop(0.0, Color.WHITE), new Stop(0.3, Color.RED), new Stop(1.0, Color.DARKRED)};
falsePaint = new RadialGradient(0.0, 0.0, -10.0, -10.0, 50, false, CycleMethod.NO_CYCLE, falseStops);

Stop[] trueStops = new Stop[]{new Stop(0.0, Color.WHITE), new Stop(0.3, Color.GREENYELLOW), new Stop(1.0, Color.DARKGREEN)};
truePaint = new RadialGradient(0.0, 0.0, -10.0, -10.0, 50, false, CycleMethod.NO_CYCLE, trueStops);

ellipse = EllipseBuilder.create().
radiusX(30).
radiusY(30).
fill(falsePaint).
build();

DropShadow ds = new DropShadow();
ds.setOffsetY(3.0f);
ds.setColor(Color.color(0.4f, 0.4f, 0.4f));

ellipse.setEffect(ds);

Slider

slider = SliderBuilder.create().
min(model.getAValue()).
max(model.getBValue()).
showTickMarks(true).
showTickLabels(true).
majorTickUnit(20).
minorTickCount(3).
prefWidth(300).
blockIncrement(0.1f).
build();

Status Labels

aValueText = TextBuilder.create().build();
bValueText = TextBuilder.create().build();
aureaText = TextBuilder.create().build();

Solve Button

solveButton = ButtonBuilder.create().text("Solve").build();

Add the solve action

solveButton.setOnAction(new EventHandler() {
@Override
public void handle(ActionEvent arg0) {
model.setAValue(61.8);
}
});

Put it all together

Using the GridPane layout:

GridPane root = new GridPane();
root.setPadding(new Insets(20, 20, 20, 20));
root.setGridLinesVisible(true);</h2>
RowConstraints rowInfo = new RowConstraints(100);
ColumnConstraints colInfo = new ColumnConstraints(100);

root.getRowConstraints().
add(rowInfo);

for (int j = 0; j &lt;= 2; j++) {
root.getColumnConstraints().
add(colInfo);
}

GridPane.setHalignment(titleText, HPos.CENTER);
GridPane.setHalignment(descriptionText, HPos.CENTER);
GridPane.setHalignment(slider, HPos.CENTER);
GridPane.setHalignment(aValueText, HPos.CENTER);
GridPane.setHalignment(ellipse, HPos.CENTER);
GridPane.setHalignment(bValueText, HPos.CENTER);
GridPane.setHalignment(solveButton, HPos.CENTER);

GridPane.setConstraints(titleText, 0, 0, 3, 1);
GridPane.setConstraints(descriptionText, 0, 1, 3, 1);
GridPane.setConstraints(slider, 0, 2, 3, 1);
GridPane.setConstraints(aValueText, 0, 3);
GridPane.setConstraints(ellipse, 1, 3);
GridPane.setConstraints(bValueText, 2, 3);
GridPane.setConstraints(solveButton, 2, 4);

Connect UI to Model

model.getAValueProperty().
bindBidirectional(slider.valueProperty());

aValueText.textProperty().
bind(model.getAValueProperty().
asString("%.1f"));
bValueText.textProperty().
bind(model.getBValueProperty().
asString("%.1f"));

aureaText.textProperty().
bind(model.getSectioAureaProperty().
asString());
<h2>Connect listener to refresh the indicator:</h2>
<pre>model.getSectioAureaProperty().
            addListener(new ChangeListener() {</pre>
@Override
public void changed(ObservableValue arg0, Boolean arg1, Boolean arg2) {
refreshIndicator();
}
});

The complete UI code

package de.jensd.javafx.aurea;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBuilder;
import javafx.scene.control.Slider;
import javafx.scene.control.SliderBuilder;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.Paint;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.EllipseBuilder;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.scene.text.TextBuilder;
import javafx.stage.Stage;

/**
*
* @author Jens Deters
*/
public class SectioAureaApplication extends Application {

private SectioModel model = new SectioModel();
private Slider slider;
private Text aValueText;
private Text bValueText;
private Text aureaText;
private Ellipse ellipse;
private Paint falsePaint;
private Paint truePaint;
private Button solveButton;

public static void main(String[] args) {
Application.launch(SectioAureaApplication.class, args);
}

@Override
public void start(Stage stage) throws Exception {
stage.setTitle("Sectio Aurea");

model = new SectioModel();
model.setAValue(0);
model.setBValue(100.9);

slider = SliderBuilder.create().
min(model.getAValue()).
max(model.getBValue()).
showTickMarks(true).
showTickLabels(true).
majorTickUnit(20).
minorTickCount(3).
prefWidth(300).
blockIncrement(0.1f).
build();

aValueText = TextBuilder.create().
build();

bValueText = TextBuilder.create().
build();

aureaText = TextBuilder.create().
build();

solveButton = ButtonBuilder.create().
text("Solve").
build();

Stop[] falseStops = new Stop[]{new Stop(0.0, Color.WHITE), new Stop(0.3, Color.RED), new Stop(1.0, Color.DARKRED)};
falsePaint = new RadialGradient(0.0, 0.0, -10.0, -10.0, 50, false, CycleMethod.NO_CYCLE, falseStops);

Stop[] trueStops = new Stop[]{new Stop(0.0, Color.WHITE), new Stop(0.3, Color.GREENYELLOW), new Stop(1.0, Color.DARKGREEN)};
truePaint = new RadialGradient(0.0, 0.0, -10.0, -10.0, 50, false, CycleMethod.NO_CYCLE, trueStops);

ellipse = EllipseBuilder.create().
radiusX(30).
radiusY(30).
fill(falsePaint).
build();

DropShadow ds = new DropShadow();
ds.setOffsetY(3.0f);
ds.setColor(Color.color(0.4f, 0.4f, 0.4f));

ellipse.setEffect(ds);

Text titleText = TextBuilder.create().
text("Sectio Aurea").
effect(ds).
font(Font.font(null, FontWeight.BOLD, 32)).
build();

Text descriptionText = TextBuilder.create().
text("Move the slider until your hit the golden section.\nHint: use the cursor keys for exact control.").
textAlignment(TextAlignment.CENTER).
build();

// Put it all together
GridPane root = new GridPane();
root.setPadding(new Insets(20, 20, 20, 20));
root.setGridLinesVisible(false);

RowConstraints rowInfo = new RowConstraints(100);
ColumnConstraints colInfo = new ColumnConstraints(100);

root.getRowConstraints().
add(rowInfo);
root.getRowConstraints().
add(rowInfo);

for (int j = 0; j <= 2; j++) {
root.getColumnConstraints().
add(colInfo);
}

GridPane.setHalignment(titleText, HPos.CENTER);
GridPane.setHalignment(descriptionText, HPos.CENTER);
GridPane.setHalignment(slider, HPos.CENTER);
GridPane.setHalignment(aValueText, HPos.CENTER);
GridPane.setHalignment(ellipse, HPos.CENTER);
GridPane.setHalignment(bValueText, HPos.CENTER);
GridPane.setHalignment(solveButton, HPos.CENTER);

GridPane.setConstraints(titleText, 0, 0, 3, 1);
GridPane.setConstraints(descriptionText, 0, 1, 3, 1);
GridPane.setConstraints(slider, 0, 2, 3, 1);
GridPane.setConstraints(aValueText, 0, 3);
GridPane.setConstraints(ellipse, 1, 3);
GridPane.setConstraints(bValueText, 2, 3);
GridPane.setConstraints(solveButton, 2, 4);

root.getChildren().
addAll(titleText, descriptionText, slider, aValueText, ellipse, bValueText, solveButton);

bindProperties();

stage.setScene(new Scene(root, 350, 380));
stage.show();

}

private void refreshIndicator() {
if (model.getSectioAureaProperty().
get()) {
ellipse.fillProperty().
set(truePaint);

} else {
ellipse.fillProperty().
set(falsePaint);
}
}

private void bindProperties() {

model.getAValueProperty().
bindBidirectional(slider.valueProperty());

aValueText.textProperty().
bind(model.getAValueProperty().
asString("%.1f"));
bValueText.textProperty().
bind(model.getBValueProperty().
asString("%.1f"));

aureaText.textProperty().
bind(model.getSectioAureaProperty().
asString());

model.getSectioAureaProperty().
addListener(new ChangeListener() {

@Override
public void changed(ObservableValue arg0, Boolean arg1, Boolean arg2) {
refreshIndicator();
}
});

solveButton.setOnAction(new EventHandler() {

@Override
public void handle(ActionEvent arg0) {
model.setAValue(61.8);
}
});

}
}

_____________________________________________________

here’s the NetBeans project: SectioAurea.zip