Designing JavaFX Business Applications (Part 1)

The JavaFX community is really growing and more and more open source frameworks and first real business applications appear on the internet.
While most of the open source frameworks are just at the beginning I think that many of them demonstrate what could be done with JavaFX. While tracking all this APIs and Open Source Frameworks (thanks to Jonathan Giles and his weekly link overview) I’m trying to prepare some best practice pattern for JavaFX application development. I thought a lot about this topic and think that it’s the right time to share my opinion with you. Sure everything that comes now is only my way of looking at this stuff and no whitepaper. If you think that my thoughts are wrong or you have some advancements please let me know!

While the architecture of applications is a so big topic I will break this down and only take a deeper look at classic business applications. But I think that most of the practices that I will describe can be used in other kinds of applications, too.

The classic business application

Ok, first of all I will define what a classic business app is. I think that most of this applications or systems based on a client server architecture. In this case it is not important if the client is a rich desktop client or a JSF based web client. I a normal scenario you will have a 3 tier architecture that is splitted is a persitence, businesslogic and view layer.

3tier

If you have a JSF based web client your view can directly access the EJB beans out of the view by using the Expression Language (EL). By doing so you can handle the properties of the EJB bean or call methods on it. Here is a short example:

jsf

If you have a desktop client (or maybe a webclient that is written in another language / framework like AngularJS) you need a middleware to interact with the server. Here you will hopefully depend on a standard like SOAP, REST or WebSocket. By doing so you can achieve the same features in your application that you will have while using JSF and EL.

JavaFX middleware

As you can see there is no technical barrier that will stop you to connect a JavaFX client with a JEE Backend. A good example for this is CaptainCasa that provides a JSP and JavaFX based client for business applications that are created with this framework.

If you connect your JavaFX app to a backend server you need to pay attention to multi threading. A request to the server can take some time and if you execute this inside the JavaFX application thread your complete client will freeze. To avoid this problems you can fall back on one of the great open source frameworks that are currently out. In my opinion you should take a deeper look at

If you only need REST Requests as the middleware layer DataFX is in my eyes the best API at the moment. You can define your complete server infrastructure by only using JEE defaults as mentioned before. DataFX will only be needed at client site and handle all the REST calls for you.

dfx

 

While using DataFX all requested business values will be stored in JavaFX properties and you can simple use them in the JavaFX application thread. You can find a simple demo that access iTunes REST web services here.

For a more complex communication I would prefer to use RedFX or Open Dolphin. This two frameworks need a API on server site too. RedFX uses the default JEE WebSocket API for communication and Open Dolphin has no default communication layer (as far as I know) but can easily be used with REST. If you use one of this framework your application stack may look like this:

redfx

 

Until now I haven’t worked with one of this two framework. Cause of this I can’t tell you what are the fine differences between this two framework and in which specific usecase you should use the one or the other.

Once the middelware is created and you can access all your business objects on client side you need to form a concept for the client.

Hope you liked my short overview of JavaFX related middleware. The next post in this series will cover the client site. Here I will cover dependency injection in JavaFX applications.

Aquatecture

While Claudine is working on all the needed Skins for AquaFX I will use the time to show you some of the internal API stuff of AquaFX that Claudine has developed. Once the project is released you can easily style your complete application by just calling

AquaFx.style();

This will set the CSS Styles for all controls that are supported by AquaFX for you. Once this is done your application should look like a native one.

While working a lot with Aqua and reading all the Apple style guides, etc. we noticed that simply setting one style for every control type is not enough to provide a great Aqua Look and Feel for JavaFX. Many native applications use the default controls like Buttons in different variations. For example you can have smaller controls or buttons with a more rounded border than the default one. Here is good overview about the different size variations of components:

sizeVariant

This Image is taken from the Apple documentation of the native Swing Look&Feel for Mac OS.

When using the Aqua L&F in Swing you can change the behavior of a component by adding a String as a clientProperty to the component:

component.putClientProperty("JComponent.sizeVariant", "mini");

I think with AquaFX Claudine found a better way to provide this different styles by simply providing Enums for all different designs. So you can change the size of the component by simply using this enum:

public enum ControlSizeVariant implements StyleDefinition {

REGULAR,

SMALL,

MINI;

@Override public String getStyleName() {
...
}
...
}

Now you can skin a button as a small control with just a method-call:

AquaFx.resizeControl(myButton, ControlSizeVariant.SMALL);

For doing so you only need the AquaFX class that is a static facade for all features AquaFX will provide. So a normal developer will only need to now this class and its’ internal methods to skin and configure an application with AquaFX.

But the rezise as shown above is not the only skin variation you can define. With AquaFX you can easily mix different variations, too. The Facade offers a method for that:

AquaFx.skin(myButton, ButtonType.ROUND_RECT, ControlSizeVariant.SMALL);

Cause all Enums implement the StyleDefinition interface you can commit as many as you want for a control. AquaFX will try to create the best look for you. Here is a example of some controls with a custom styling:

custom

At the moment some combinations of StyleDefinition don’t make sense and I gave Claudine the hint to think about a fluent approach for skinning this variations. So maybe this is not the final API. But I think it’s at a good point to share this ideas and features with you. Hope you like it.

sbt-fxml: The missing link between FXML and your code

Greetings web! I was invited to write a guest post here about a little JavaFX project I started not long ago: sbt-fxml. It’s a plugin for SBT and it tries hard to generate boring code for you so you don’t have to.

It scans for FXML files – either hand written or created by Scene Builder – parses them and creates controller classes with a proper name, package structure, imports, declarations and types. That’s right: types! So now your FXML files suddenly type check thus allowing you to find mistakes almost instantly. And because of SBT, you don’t even have to manually start the build for it. It happens as soon as you save your files.

scala

What exactly are controller classes?

Controllers are simple POJOs into which the JavaFX runtime injects nodes from an FXML scenegraph. They provide the coder with a way to reference these nodes, so she doesn’t have to use node.lookup("#cssSelector") which has issues itself. When loading an FXML, everything with an fx:id gets injected. To give an example, the following FXML:

<Button fx:id="meep" />

could be accessed by a controller like this:

public class MyController {
    @FXML
    private Button meep;
}

This is a minimalistic controller skeleton created by Scene Builder (View -> Show Sample Controller Skeleton) and it is indeed a good example of how little code is needed to use FXML files.

 

That’s easy! Why the plugin?

Even if it’s only 4 lines of code it’s still code I don’t want to write. DRY, you know. It’s code which was autogenerated by a tool and I don’t see why it shouldn’t stay that way. And although SceneBuilder can give you an example controller, the generated code is neither pretty nor is the generation automated, so you are likely to have a gap between FMXL and your codebase. Sbt-fxml does not have this limitation as it creates bindings the moment you save your FXML. Additionaly it does it’s best to format the code nicely so it looks as whether it was hand written:

// Auto generated by sbt-fxml, changes will be overwritten

package com.example

import javafx.fxml.FXML
import javafx.scene.control.Button

object MyController {
  @FXML
  var meep: Button = ???
}

 

What’s next?

The plugin currently emits Scala code only. This is not by design, but felt like the natural choice for me when creating the plugin. This is likely to change in the future, though. Speaking of future, here is a list of what will be next:

  • Support generic nodes like ListView<?>
  • Handle many FXML files using the same controller class
  • Delete outdated controller classes
  • Implement creation of Java controller classes
  • Add more options to customize the output (indentation, etc.)
  • De-couple from SBT to allow other build tools (e.g. Maven, Gradle, Buildr, Ant, …) to leverage sbt-fxml’s functionality
  • Create a stand alone main so it can be used from the command line

I am currently writing tests and refactor the code in order to meet those goals. At the end there will be a nice specification of what sbt-fxml can do and after the first three tasks, I will release a 1.0. You don’t have to wait that long, though: There is a 1.0-SNAPSHOT, so if you’re curious, feel free to try sbt-fxml!

Thanks for reading!

Phillip Dörfler @phdoerfler

 


This article is the first guest post at guigarage. I hope you like it :)
In my eyes this article afford guigarage a wider range of JavaFX related stuff.
If anyone is interested to write a guest post at guigarage please ping me!
Hendrik

The native ones are not sleeping

As time goes by, there are lots of freshly skinned controls, which are waiting to be shown. So here comes a little “update post”.

 

New Components

ComboBoxes

combobox

combobox-editable

ColorPickers
colorpicker

ProgressIndicator
progressIndocator-indeterminate

Toggles & PillToggles
toggles_pills

Sliders and TabPanes
tabpane & sliders

 

Trees
tree

Tables
tableview

 

TreeTables
treetable

 

Lists
listview

Toolbar
toolbar

 

Since MacOS has some special Controls that are not in JavaFX out-of-the-box, I started to add some of them, which will be available when using AquaFX.

Here are some of them:
AquaFX-specials

 

You can see some a HelpButton, a different rounded Variant for Buttons, a ShareButton and a GroupBox.
There are many more of them on my queue.

 

So with those Buttons, you can start to make neat dialogs without any pain. This can result in:

network-demo

 

or:

date-and-time-demo

 

The SearchField is still missing, but since it is used so often in Mac OS in definitely will get this done, too. Just didn’t want to keep back some results from you.

My next blogpost will be about some useful HOW-TOs, I had to find out to go on, e.g. “How do I make Toolbars working together with the top of the dialog?” “How to make MenuBar showing on top in MacOS Menu?”. So keep on visiting us.

Assertions and Rules in MarvinFX

Today I added some new features to MarvinFX. For all basic property types (String, Number, Boolean, etc…) MarvinFX will provide methods to check some common assertions for this properties. All this methods will be part of the PropertySupervisor classes. Here is a short example that tests a String property:

@Test
public void test5() {
	TextField textField = new TextField("Hello MarvFX");
	MarvinFx.show(textField);
	
	TextfieldFixture<TextField> textfieldFixture = new TextfieldFixture<>(textField);
	StringPropertySupervisor supervisor = textfieldFixture.createTextPropertySupervisor();

	supervisor.assertStringEndsWith("MarvFX");
	supervisor.assertStringStartsWith("Hello");
	supervisor.assertStringLenghtIsEquals(12);
	supervisor.assertStringLenghtIsGreaterThan(11);
	supervisor.assertStringLenghtIsLessThan(13);
}

All this methods work internally with so called MarvinFXRules. For every assertion MarvinFX provides a special rule. You can simply write your own rules and check them with the supervisor:

@Test
public void test5() {
	TextField textField = new TextField("Hello MarvFX");
	MarvinFx.show(textField);
	
	TextfieldFixture<TextField> textfieldFixture = new TextfieldFixture<>(textField);
	StringPropertySupervisor supervisor = textfieldFixture.createTextPropertySupervisor();

	//Custom Rule
	StringEndsWithRule rule = new StringEndsWithRule("MarvFX");
	supervisor.checkAssertion(rule);
}

Because every assertion is encapsulated in a MarvinRule you can use a underlying API and boolean logic to combine them:

@Test
public void test5() {
	TextField textField = new TextField("Hello MarvFX");
	MarvinFx.show(textField);
	
	TextfieldFixture<TextField> textfieldFixture = new TextfieldFixture<>(textField);
	StringPropertySupervisor supervisor = textfieldFixture.createTextPropertySupervisor();

	StringEndsWithRule rule1 = new StringEndsWithRule("MarvFX");
	StringStartsWithRule rule2 = new StringStartsWithRule("Hello");
	StringStartsWithRule wrongRule1 = new StringStartsWithRule("ABC");
		
	supervisor.checkAssertion(rule1.and(rule2));
	supervisor.checkAssertion(rule1.or(rule2));
	supervisor.checkAssertion(wrongRule1.or(rule1));
	supervisor.checkAssertion(wrongRule1.or(rule1).and(rule2));
	supervisor.checkAssertion(rule1.and(rule2).or(wrongRule1));
	supervisor.checkAssertion(rule1.and(rule2).or(wrongRule1.or(rule2)));
}

Hope you like this ;)

Use native Aqua icons in JavaFX

While planning AquaFX we found a way how to access Mac OS specific icons without using any closed APIs or Mac OS related classes. We wrapped this in a simple util class. While using this on a Mac you will receive images by the underlying OS. On any other OS the function will return “null”. We currently discuss if this should be part of AquaFX because this will be a part that is (under the hood) OS specific. All control skins of AquaFX are cross-platform. So you can skin your JavaFX application on Windows like a native Mac OS application (if you want :D ). Because we currently don’t know if this sources will ever be part of AquaFX I simple will post them here:
This enum contains all fetch able images that we found:

public enum NsImageIcon {
    QUICK_LOOK_TEMPLATE("NSQuickLookTemplate"), BLUETOOTH_TEMPLATE(
            "NSBluetoothTemplate"), I_CHAT_THEATER_TEMPLATE(
            "NSIChatTheaterTemplate"), SLIDESHOW_TEMPLATE("NSSlideshowTemplate"), ACTION_TEMPLATE(
            "NSActionTemplate"), SMART_BADGE_TEMPLATE("NSSmartBadgeTemplate"), PATH_TEMPLATE(
            "NSPathTemplate"), INVALID_DATA_FREESTANDING_TEMPLATE(
            "NSInvalidDataFreestandingTemplate"), LOCK_LOCKED_TEMPLATE(
            "NSLockLockedTemplate"), LOCK_UNLOCKED_TEMPLATE(
            "NSLockUnlockedTemplate"), GO_RIGHT_TEMPLATE("NSGoRightTemplate"), GO_LEFT_TEMPLATE(
            "NSGoLeftTemplate"), RIGHT_FACING_TRIANGLE_TEMPLATE(
            "NSRightFacingTriangleTemplate"), LEFT_FACING_TRIANGLE_TEMPLATE(
            "NSLeftFacingTriangleTemplate"), ADD_TEMPLATE("NSAddTemplate"), REMOVE_TEMPLATE(
            "NSRemoveTemplate"), REVEAL_FREESTANDING_TEMPLATE(
            "NSRevealFreestandingTemplate"), FOLLOW_LINK_FREESTANDING_TEMPLATE(
            "NSFollowLinkFreestandingTemplate"), ENTER_FULL_SCREEN_TEMPLATE(
            "NSEnterFullScreenTemplate"), EXIT_FULL_SCREEN_TEMPLATE(
            "NSExitFullScreenTemplate"), STOP_PROGRESS_TEMPLATE(
            "NSStopProgressTemplate"), STOP_PRPGRESS_FREESTANDING_TEMPLATE(
            "NSStopProgressFreestandingTemplate"), REFRESH_TEMPLATE(
            "NSRefreshTemplate"), REFRESH_FREESTANDING_TEMPLATE(
            "NSRefreshFreestandingTemplate"), FOLDER("NSFolder"), TRASH_EMPTY(
            "NSTrashEmpty"), TRASH_FULL("NSTrashFull"), HOME_TEMPLATE(
            "NSHomeTemplate"), BOOKMARKS_TEMPLATE("NSBookmarksTemplate"), CAUTION(
            "NSCaution"), STATUS_AVAILABLE("NSStatusAvailable"), STATUS_PARTIALLY_AVAILABLE(
            "NSStatusPartiallyAvailable"), STATUS_UNAVAILABLE(
            "NSStatusUnavailable"), STATUS_NONE("NSStatusNone"), APPLICATION_ICON(
            "NSApplicationIcon"), MENU_ON_STATE_TEMPLATE(
            "NSMenuOnStateTemplate"), MENU_MIXED_STATE_TEMPLATE(
            "NSMenuMixedStateTemplate"), USER_GUEST("NSUserGuest"), MOBILE_ME(
            "NSMobileMe"), MULTIPLE_DOCUMENTS("NSMultipleDocuments"), USER(
            "NSUser"), USER_GROUP("NSUserGroup"), EVERYONE("NSEveryone"), BONJOUR(
            "NSBonjour"), DOT_MAC("NSDotMac"), COMPUTER("NSComputer"), FOLDER_BURNABLE(
            "NSFolderBurnable"), FOLDER_SMART("NSFolderSmart"), NETWORK(
            "NSNetwork"), USER_ACCOUNTS("NSUserAccounts"), PREFERENCES_GENERAL(
            "NSPreferencesGeneral"), ADVANCED("NSAdvanced"), INFO("NSInfo"), FONT_PANEL(
            "NSFontPanel"), COLOR_PANEL("NSColorPanel"), ICON_VIEW_TEMPLATE(
            "NSIconViewTemplate"), LIST_VIEW_TEMPLATE("NSListViewTemplate"), COLUMN_VIEW_TEMPLATE(
            "NSColumnViewTemplate"), FLOW_VIEW_TEMPLATE("NSFlowViewTemplate");

    private String name;

    private NsImageIcon(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

And here is the loader class:

import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;

import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;

public class NsImageIconLoader {

    public static Image load(NsImageIcon icon) {
        System.setProperty("java.awt.headless", "false");
        java.awt.Image awtImage = Toolkit.getDefaultToolkit().getImage(
                "NSImage://" + icon.getName());
        BufferedImage bufferedImage = null;
        if (awtImage instanceof BufferedImage) {
            bufferedImage = (BufferedImage) awtImage;
        } else {
            bufferedImage = new BufferedImage(awtImage.getWidth(null),
                    awtImage.getHeight(null), BufferedImage.TYPE_INT_ARGB);
            Graphics g = bufferedImage.createGraphics();
            g.drawImage(awtImage, 0, 0, null);
            g.dispose();
        }
        return SwingFXUtils.toFXImage(bufferedImage, null);
    }
}

Here is a overview of all icons that we have found:
native icons

If anyone knows more icon names that can be loaded by Mac OS please let us know ;)

Introducing MarvinFx

For all my current JavaFX work I need a simple test framework to check the behavior of controls or complete scenes. Since I’m working more and more with the Property API I mainly wanted to to test the properties and their behavior of controls and scenes.

FEST is doing a great job for automated tests in Swing and with JemmyFX a first framework for JavaFX is available. But both of this framework don’t have a (good) support for Properties.

Because of this I started my own testing framework for JavaFX. MarvinFX has the goal to easily test JavaFX controls and scenes with a special attention on properties. The framework is currently in a very early state and only a few parts are implemented. But I think that already the current state can point out where the journey will lead. And maybe I will receive some helpful suggestions.

You can simply use MarvinFX with a JUnit test. By using Marvin you can create a JavaFX Scene of the Application part you want to test:

@Test
public void test1() {
	Button b1 = new Button("Test123");
	MarvinFx.show(b1);
}

Marvin will generate a Parent (StackPane) for the Button and put everything in a Scene. The Scene will automatically be shown on the screen.

To test parts of the ui you need a Robot that will generate user interactions for you. It is planned that MarvinFX will provide a OS based robot (by AWTRobot) and a Java based robot (by JFXRobot) under the surface. At the current state the mouse handling of the robot is working.

@Test
public void test2() {
	Button b1 = new Button("Test123");
	MarvinFx.show(b1);
	NodeFixture<Button> b1Fixture = new NodeFixture<Button>(b1);
	b1Fixture.mouse().click();
	b1Fixture.mouse().click(MouseButton.SECONDARY);
}

As you can see MarvinFX uses Fixture-classes like FEST does. The fixture is a wrapper for a node and provides all methods that are needed to test the node.

To check the state of properties MarvinFX provide so called PropertySupervisor classes. By using them you can write unit tests for JavaFX properties. A PropertySupervisor is a wrapper class for a property:

@Test
public void test3() {
	Button b1 = new Button("Test123");
	MarvinFx.show(b1);
	PropertySupervisor<String> textPropertySupervisor = new PropertySupervisor<>(b1.textProperty());
	textPropertySupervisor.assertCurrentValue("Test123");

	TextField textField = new TextField("1");
	TextfieldFixture textfieldFixture = new TextfieldFixture(textField);
	PropertySupervisor<String> textSupervisor = textfieldFixture.createTextPropertySupervisor();
}

By using the supervisors you can easily check the current value of a property. But a supervisor can do more. You can define rules that will be checked in the future while a property will change:

@Test
public void test3() {
	TextField textField = new TextField("1");
	MarvinFx.show(textField);
	TextfieldFixture textfieldFixture = new TextfieldFixture(textField);
	PropertySupervisor<String> textSupervisor = textfieldFixture.createTextPropertySupervisor();

	textSupervisor.assertWillChange();
	textSupervisor.assertWillChangeByDefinedCount(2);
	textSupervisor.assertWillChangeThisWay("7", "14");
	textfieldFixture.setText("7");
	textfieldFixture.setText("14");
	textSupervisor.confirm();
}

Property supervisors offers some methods that start with “assertWill…”. All this methods defines a rule for the supervisor and every time the property will changed all rules of the supervisor will be checked. After all user interaction is done (in this case by setting the text) you need to invoke a confirm() on the supervisor. If any of the rules were failed the unit test will fail with the confirmation. By calling confirm() all defined rules will be deleted and the supervisor can be used for other tests.

Putting all this stuff together you can simply write unit tests for your JavaFX controls and scenes. Here is a basic example that uses all the features and checks the behavior of a simplified Scene:

@Test
public void test4() {
	final TextField textField = new TextField("1");
	Button button = new Button("Button");
	button.setOnAction(new EventHandler<ActionEvent>() {
			
		@Override
		public void handle(ActionEvent event) {
			int value = Integer.parseInt(textField.getText()) * 2;
			textField.setText(value + "");
		}
	});
	MarvinFx.show(VBoxBuilder.create().children(textField, button).build());
		
	TextfieldFixture textfieldFixture = new TextfieldFixture(textField);
	PropertySupervisor<String> textSupervisor = textfieldFixture.createTextPropertySupervisor();
	NodeFixture<Button> buttonFixture = new NodeFixture<Button>(button);
		
	textSupervisor.assertValueIsNotNull();
	textSupervisor.assertCurrentValue("1");
	buttonFixture.mouse().click();
	textSupervisor.assertCurrentValue("2");
		
	textSupervisor.assertWillChange();
	textSupervisor.assertWillChangeByDefinedCount(4);
	textSupervisor.assertWillChangeThisWay("4", "8", "16", "32");
	buttonFixture.mouse().click(4);
	textSupervisor.confirm();
		
	textSupervisor.assertWillNeverChange();
	textSupervisor.confirm();
		
	textSupervisor.assertWillChange();
	textSupervisor.assertWillChangeByDefinedCount(2);
	textSupervisor.assertWillChangeThisWay("7", "14");
	textfieldFixture.setText("7");
	buttonFixture.mouse().click();
	textSupervisor.confirm();
}

MarvinFX is hosted at github. At the moment there is no JavaDoc and as I said the API is not finished and some parts are buggy at the moment. But maybe some people have good ideas for Marvin or can offer some feedback :)

Update for the native ones

Since my project was accepted, I was keen on starting with the first components. Now I want to show you what is the result. 

Remember the shutdown dialog?

As Jonathan suggested, the whole project is realized in JavaFX 8.

In the first step, the proof-of-concept dialog had to be migrated to be up-to-date again. Pretty soon, I could welcome my dialog in JavaFX8:

shutdown_fx8

All components look like mountain lion again.

You want more?

What about those neat components:

TextField:
textfield

PasswordField:
pw

TextArea:
textarea

RadioButton:
radio#

CheckBox:
check

ChoiceBox:
choice

ToggleButton:
toggle

ScrollBar:
scrollbar1

scrollbar2

Just for the moment, everything is crafted in a little dialog, where I have an overview over all results untill now.
The good news in this context is, that all of this stuff works on retina- and non-retina macs and looks the same:
demodialog

The development and different struggles

There are some points, which had to be decided before I really could start and which are not absolutely clear.
Currently all CSS-styling is overriding caspian.css, as it is the default style. But we all look forward to modena replacing caspian for JavaFX 8. This may cause some trouble in future concerning new controls, which do not have Mac OS-Styling yet. For this reason, it is not that clear, how to apply mac_os.css to an application. Hendrik describes the different variations using the StyleManager in his latest blogpost. Thoughtless usage of style management also causes trouble with PopUp-components.
The main approach in styling the components is, using CSS as much as possible. Everything, that is not possible in CSS e.g. multiple effects on one component or animations is implemented in Aqua*Skins, which simply override the skin of the affected control. In this way, effects and animations are no problem.
One open struggle is the behavior of the hover in default-buttons. In MacOS default-buttons are blinking from a light blue to a darker blue. If the mouse hovers into the button there is a tiny little flashing until the next repaint, which shows the button in his non-default state. Just some milliseconds, but very distracting.. ;-) Until now, there is no way of disabling the hover-effect in my skin class, which is worth a Jira-Issue.

What comes next?

Right now I am working on finishing the PopUp of ChoiceBox an ScrollBar-animation. More components will to come up soon.

Global Stylesheet for your JavaFX Application

You can style your JavaFX Scene by CSS as you can read here and here.All this examples show how to apply a specific Stylesheet to one Scene by using

myScene.getStylesheets().add("path/to/custom.css");

Inside the SceneGraph of this Scene all Nodes will use the defined Stylesheets. But while your Application grows you will normally have more than one Scene. Each Window in JavaFX holds its own Scene. Even if your Application only uses one Stage you will normally have more than one window while every ContextMenu is Window. So if you use custom ContextMenus or a ChoiceBox inside your application this Components will technically be displayed in a separate Window with a new Scene and SceneGraph. But with the code mentioned above only “myScene” will use the custom Stylesheet. The Scene of the ContextMenu will not be affected by this. One trick here is to set the Stylesheet manually to the Scene of the Window:

myContextMenu.getScene().getStylesheets().add("path/to/custom.css");

But this is only a bad workaround and you won’t do this for every ContextMenu. When you use a ChoiceBox you even can’t access the Scene of the popup because this is defined in private methods of the ChoiceBoxSkin.

But there is a way to set a global Stylesheet to all Scenes. By using the JavaFX 8 class StyleManager you can define the default CSS files. The class uses the singleton pattern and can easily accepted. The following code will add a CSS file to all Stylesheets of all Scenes:

StyleManager.getInstance().addUserAgentStylesheet(AQUA_CSS_NAME);

Currently there is one bug with this. The default Stylesheet (currently caspian) is defined inside the StyleManger, too. But the default will not be set until a first Node is created. When adding a additional user defined Stylesheet a Exception is thrown. So to avoid problems you have to set the default CSS before adding a custom one. This can currently only done by calling a private API:

PlatformImpl.setDefaultPlatformUserAgentStylesheet();
StyleManager.getInstance().addUserAgentStylesheet(AQUA_CSS_NAME);

I will open a issue at http://javafx-jira.kenai.com about this behavior.

addition

With the help of Jonathan Giles (see comments) I found a better way without using private APIs. You can easily set the default stylesheet by using “Application.setUserAgentStylesheet(String url)”. If you use null as parameter value the default stylesheet (currently caspian) will be used. So here is the code without using a private API:

Application.setUserAgentStylesheet(null);
StyleManager.getInstance().addUserAgentStylesheet(AQUA_CSS_NAME);

DataFX: ObservableExecutor Preview

Since December we are working on a new DataFX version. DataFX will provide a new low level API for multithreading and background tasks in JavaFX. With this API everyone can create new and custom DataSources that will fetch data in background and publish it to JavaFX properties (like you can do with the SwingWorker in Swing). Additionally we will provide some basic concurrency features like the invokeAndWait-method.

Next to this features we created a new Executor class that offers some additional features for the use with JavaFX. The ObservableExecutor holds a ListProperty with all currently scheduled or running tasks. By using this Property you can easily observe all tasks in your UI. We will provide a ListCell class to visualize the running tasks of the executor with only a few lines of code:

Executor executor = new ObservableExecutor();
ListView<Service<?>> list = new ListView<>();
list.setCellFactory(new ServiceListCellFactory());
list.itemsProperty().bind(executor.currentServicesProperty());

The ObservableExecutor uses the wrapper pattern to hold any Executor. Because all task are wrapped into Services you can easily access the title, message or progress of any task. A short example that shows the current state of the API can be found here:

Because Runnable & Callable normally do not provide title, message and progress properties we created extended interfaces (DataFXRunnable & DataFXCallable) where all this functions are injected while using them with the ObservableExecutor.
At the current state tasks can be passed to an ObservableExecutor by the following methods:

public <T> Worker<T> submit(Service<T> service);

public <T> Worker<T> submit(Task<T> task);

public <T> Worker<T> submit(Callable<T> callable);

public Worker<Void> submit(Runnable runnable);

public void execute(Runnable runnable);

There are some additional features, too. You can mark a task as not cancelable for example.
Hope you like this stuff!