RxJavaFX
RxJava bindings for JavaFX
Install / Use
/learn @ReactiveX/RxJavaFXREADME

RxJavaFX: JavaFX bindings for RxJava
NOTE: UNSUPPORTED, PLEASE FOLLOW FORKS FOR NEWER DEVELOPMENTS AND DEPLOYMENTS
https://github.com/torakiki/RxJavaFX
Read the free eBook Learning RxJava with JavaFX to get started.
RxJavaFX is a lightweight library to convert JavaFX events into RxJava Observables/Flowables and vice versa. It also has a Scheduler to safely move emissions to the JavaFX Event Dispatch Thread.
NOTE: To use with Kotlin, check out RxKotlinFX to leverage this library with extension functions and additional operators.
Master Build Status
<a href='https://travis-ci.org/ReactiveX/RxJavaFX/builds'><img src='https://travis-ci.org/ReactiveX/RxJavaFX.svg?branch=2.11.x'></a>
Documentation
Learning RxJava with JavaFX - Free eBook that covers RxJava from a JavaFX perspective.
Learning RxJava - Packt book covering RxJava 2.0 in depth, with a few RxJavaFX examples.
1.x Binaries
Binaries and dependency information for Maven, Ivy, Gradle and others can be found at http://search.maven.org.
Example for Maven:
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjavafx</artifactId>
<version>1.x.y</version>
</dependency>
Gradle:
dependencies {
compile 'io.reactivex:rxjavafx:1.x.y'
}
2.x Binaries
RxJavaFX 2.x versions uses a different group ID io.reactivex.rxjava2 to prevent clashing with 1.x dependencies. Binaries and dependency information for Maven, Ivy, Gradle and others can be found at http://search.maven.org.
Example for Maven:
<dependency>
<groupId>io.reactivex.rxjava2</groupId>
<artifactId>rxjavafx</artifactId>
<version>2.x.y</version>
</dependency>
Gradle:
dependencies {
compile 'io.reactivex.rxjava2:rxjavafx:2.x.y'
}
Features
RxJavaFX has a comprehensive set of features to interop RxJava with JavaFX:
- Factories to turn
Node,ObservableValue,ObservableList, and other component events into an RxJavaObservable - Factories to turn an RxJava
ObservableorFlowableinto a JavaFXBinding. - A scheduler for the JavaFX dispatch thread
Node Events
You can get event emissions by calling JavaFxObservable.eventsOf() and pass the JavaFX Node and the EventType you are interested in. This will return an RxJava Observable.
Button incrementBttn = new Button("Increment");
Observable<ActionEvent> bttnEvents =
JavaFxObservable.eventsOf(incrementBttn, ActionEvent.ACTION);
Action Events
Action events are common and do not only apply to Node types. They also emit from MenuItem and ContextMenu instances, as well as a few other types.
Therefore, a few overloaded factories are provided to emit ActionEvent items from these controls
Button ActionEvents
Button incrementBttn = new Button("Increment");
Observable<ActionEvent> bttnEvents =
JavaFxObservable.actionEventsOf(incrementBttn);
MenuItem ActionEvents
MenuItem menuItem = new MenuItem("Select me");
Observable<ActionEvent> menuItemEvents =
JavaFxObservable.actionEventsOf(menuItem);
Other Event Factories
There are also factories provided to convert events from a Dialog, Window or Scene into an Observable. If you would like to see factories for other components and event types, please let us know or put in a PR.
Dialogs and Alerts
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirmation");
alert.setHeaderText("Please confirm your action");
alert.setContentText("Are you ok with this?");
JavaFxObservable.fromDialog(alert)
.filter(response -> response.equals(ButtonType.OK))
.subscribe(System.out::println,Throwable::printStackTrace);
Emitting Scene Events
Observable<MouseEvent> sceneMouseMovements =
JavaFxObservable.eventsOf(scene, MouseEvent.MOUSE_MOVED);
sceneMouseMovements.subscribe(v -> System.out.println(v.getSceneX() + "," + v.getSceneY()));
Emitting Window Hiding Events
Observable<WindowEvent> windowHidingEvents =
JavaFxObservable.eventsOf(primaryStage,WindowEvent.WINDOW_HIDING);
windowHidingEvents.subscribe(v -> System.out.println("Hiding!"));
ObservableValue
Not to be confused with the RxJava Observable, the JavaFX ObservableValue can be converted into an RxJava Observable that emits the initial value and all value changes.
TextField textInput = new TextField();
Observable<String> textInputs =
JavaFxObservable.valuesOf(textInput.textProperty());
Note that many Nodes in JavaFX will have an initial value, which sometimes can be null, and you might consider using RxJava's skip() operator to ignore this initial value.
ObservableValue Changes
For every change to an ObservableValue, you can emit the old value and new value as a pair. The two values will be wrapped up in a Change class and you can access them via getOldVal() and getNewVal(). Just call the JavaFxObservable.changesOf() factory.
SpinnerValueFactory<Integer> svf = new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 100);
Spinner spinner = new Spinner<>();
spinner.setValueFactory(svf);
spinner.setEditable(true);
Label spinnerChangesLabel = new Label();
Subscription subscription = JavaFxObservable.changesOf(spinner.valueProperty())
.map(change -> "OLD: " + change.getOldVal() + " NEW: " + change.getNewVal())
.subscribe(spinnerChangesLabel::setText);
ObservableList, ObservableMap, and ObservableSet
There are several factories to emit many useful ObservableList, ObservableMap, and ObservableSet events as Observables. These all can be found as static factory methods in the JavaFxObservable static class.
|Factory Method|Parameter Type|Return Type|Description|
|---|---|---|---
|emitOnChanged()|ObservableList<T>|Observable<ObservableList<T>>|Emits the entire ObservableList every time it changes|
|additionsOf()|ObservableList<T>|Observable<T>|Emits additions to an ObservableList|
|removalsOf()|ObservableList<T>|Observable<T>|Emits removals from an ObservableList|
|updatesOf()|ObservableList<T>|Observable<ListChange<T>>|Emits every item that was the result of a change to an ObservableList, with an ADDED, REMOVED, or UPDATED flag|
|distinctChangesOf()|ObservableList<T>| Observable<ListChange<R>>|Emits only distinct addtions and removals to an ObservableList|
|distinctMappingsOf()|ObservableList<T>, Func1<T,R>| Observable<ListChange<R>>|Emits only distinct additions and removals to an ObservableList and emits the mapping|
|distinctChangesOf()|ObservableList<T>, Func1<T,R>| Observable<ListChange<R>>|Emits only distinct additions and removals to an ObservableList based on a mapping|
|emitOnChanged()|ObservableMap<K,T>|Observable<ObservableMap<K,T>>|Emits the entire ObservableMap every time it changes|
|additionsOf()|ObservableMap<K,T>|Observable<Map.Entry<K,T>>|Emits every Map.Entry<K,T> added to an ObservableMap|
|removalsOf()|ObservableMap<K,T>|Observable<Map.Entry<K,T>>|Emits every Map.Entry<K,T> removed from an ObservableMap|
|changesOf()|ObservableMap<K,T>|Observable<MapChange<K,T>>|Emits every key/value pair with an ADDED or REMOVED flag.|
|emitOnChanged()|ObservableSet<T>|Observable<ObservableSet<T>>|Emits the entire ObservableSet every time it changes|
|additionsOf()|ObservableSet<T>|Observable<T>|Emits every addition to an ObservableSet|
|removalsOf()|ObservableSet<T>|Observable<T>|Emits every removal to an ObservableSet|
|changesOf()|ObservableSet<T>|Observable<SetChange<T>|Emits every item ADDED or REMOVED item from an ObservableSet with the corresponding flag|
Binding
You can convert an RxJava Observable into a JavaFX Binding by calling the JavaFxObserver.toBinding() factory. Calling the dispose() method on the Binding will handle the unsubscription from the Observable. You can then take this Binding to bind other control properties to it.
Button incrementBttn = new Button("Increment");
Label incrementLabel = new Label("");
Observable<ActionEvent> bttnEvents =
JavaFxObservable.eventsOf(incrementBttn, ActionEvent.ACTION);
Observable<String> accumulations = bttnEvents.map(e -> 1)
.scan(0,(x, y) -> x + y)
.map(Object::toString);
Binding<String> binding = JavaFxObserver.toBinding(accumulations);
incrementLabel.textProperty().bind(binding);
//do stuff, then dispose Binding
binding.dispose();
It is usually good practice to specify an onError to the Binding, just like a normal Observer so you can handle any errors that are communicated up the chain.
incrementLabel.textProperty().bind(binding, e -> e.printStackTrace());
Lazy Binding
The toBinding() factory above will eagerly subscribe the Observable to the Binding implementation. But if you want to delay the subscription to the Observable until the Binding is actually used (specifically when its getValue() is called), use toLazyBinding() instead.
Binding<String> lazyBinding = JavaFxObserver.toLazyBinding(myObservable);
This can be ha

