• Stars
    star
    520
  • Rank 85,098 (Top 2 %)
  • Language
    Java
  • License
    Apache License 2.0
  • Created about 10 years ago
  • Updated about 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

RxJava bindings for JavaFX

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

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 RxJava Observable
  • Factories to turn an RxJava Observable or Flowable into a JavaFX Binding.
  • 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 handy for data controls like TableView, which will only request values for records that are visible. Using the toLazyBinding() to feed column values will cause subscriptions to only happen with visible records.

CompositeBinding

You also have the option to use a CompositeBinding to group multiple Bindings together, and dispose() them all at once. It is the JavaFX equivalent to CompositeSubscription.

Binding<Long> binding1 = ...
bindings.add(binding1);

Binding<Long> binding2 = ... 
bindings.add(binding2);

//do stuff on UI, and dispose() both bindings
bindings.dispose();

JavaFX Scheduler

When you update any JavaFX control, it must be done on the JavaFX Event Dispatch Thread. Fortunately, the JavaFxScheduler makes it trivial to take work off the JavaFX thread and put it back when the results are ready. Below we can use the observeOn() to pass text value emissions to a computation thread where the text will be flipped. Then we can pass JavaFxScheduler.platform() to another observeOn() afterwards to put it back on the JavaFX thread. From there it will update the flippedTextLabel.

TextField textInput = new TextField();
Label fippedTextLabel = new Label();

Observable<String> textInputs =
        JavaFxObservable.valuesOf(textInput.textProperty());

sub2 = textInputs.observeOn(Schedulers.computation())
        .map(s -> new StringBuilder(s).reverse().toString())
        .observeOn(JavaFxScheduler.platform())
        .subscribe(fippedTextLabel::setText);

JavaFX Interval

There is a JavaFX equivalent to Observable.interval() that will emit on the JavaFX thread instead. Calling JavaFxObservable.interval() will push consecutive Long values at the specified Duration.

Observable<Long> everySecond = JavaFxObservable.interval(Duration.millis(1000));

Differences from ReactFX

ReactFX is a popular API to implement reactive patterns with JavaFX using the EventStream. However, RxJava uses an Observable and the two are not (directly) compatible with each other.

Although ReactFX has some asynchronous operators like threadBridge, ReactFX emphasizes synchronous behavior. This means it encourages keeping events on the JavaFX thread. RxJavaFX, which fully embraces RxJava and asynchronous design, can switch between threads and schedulers with ease. As long as subscriptions affecting the UI are observed on the JavaFX thread, you can leverage the powerful operators and libraries of RxJava safely.

If you are heavily dependent on RxJava, asynchronous processing, or do not want your entire reactive codebase to be UI-focused, you will probably want to use RxJavaFX.

Notes for Kotlin

If you are building your JavaFX application with Kotlin, check out RxKotlinFX to leverage this library through Kotlin extension functions.

Bugs and Feedback

For bugs, questions and discussions please use the Github Issues.

LICENSE

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

More Repositories

1

RxJava

RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.
Java
47,865
star
2

rxjs

A reactive programming library for JavaScript
TypeScript
30,686
star
3

RxSwift

Reactive Programming in Swift
Swift
24,267
star
4

RxAndroid

RxJava bindings for Android
Java
19,889
star
5

RxKotlin

RxJava bindings for Kotlin
Kotlin
7,036
star
6

RxGo

Reactive Extensions for the Go language.
Go
4,921
star
7

RxPY

ReactiveX for Python
Python
4,775
star
8

rxdart

The Reactive Extensions for Dart
Dart
3,338
star
9

RxCpp

Reactive Extensions for C++
C++
3,008
star
10

RxPHP

Reactive extensions for PHP
PHP
1,685
star
11

learnrx

A series of interactive exercises for learning Microsoft's Reactive Extensions Library for Javascript.
JavaScript
1,403
star
12

RxNetty

Reactive Extension (Rx) Adaptor for Netty
Java
1,384
star
13

IxJS

The Interactive Extensions for JavaScript
TypeScript
1,297
star
14

RxRuby

Reactive Extensions for Ruby
Ruby
957
star
15

RxScala

RxScala – Reactive Extensions for Scala – a library for composing asynchronous and event-based programs using observable sequences
Scala
888
star
16

RxRust

The Reactive Extensions for the Rust Programming Language
Rust
488
star
17

RxClojure

RxJava bindings for Clojure
Clojure
362
star
18

rxjs-tslint

TSLint rules targeting RxJS
TypeScript
309
star
19

RxJavaReactiveStreams

Adapter between RxJava and ReactiveStreams
Java
235
star
20

RxJavaDebug

Java
161
star
21

rxjs-docs

The home for new work on the new RxJS docs (RxJS v 5 and up). New to this space? Say hi here: https://github.com/ReactiveX/rxjs-docs/issues/24. Want to find out what's up? We're chatting here. https://github.com/ReactiveX/rxjs-docs/issues/4
TypeScript
160
star
22

RxGroovy

RxJava bindings for Groovy
Groovy
158
star
23

reactivex.github.io

ReactiveX Website
JavaScript
139
star
24

RxJavaAsyncUtil

Java
132
star
25

RxJavaString

Java
129
star
26

RxApacheHttp

RxJava bindings for Apache HTTP
Java
118
star
27

RxJavaJoins

Java
100
star
28

RxSwing

RxJava bindings for Swing
Java
98
star
29

RxJavaMath

Math operators for RxJava.
Java
96
star
30

rxjs-advent-2018

RxJS 2018 Advent Calendar
TypeScript
89
star
31

rxjs-core-notes

Notes from RxJS core meetings
77
star
32

RxJavaFileUtils

File utilities with RxJava
Java
62
star
33

RxJavaComputationExpressions

Java
60
star
34

RxJavaGuava

Java
54
star
35

RxJavaParallel

Experimental Parallel Extensions for RxJava
Java
54
star
36

RxJRuby

RxJava bindings for JRuby
Ruby
38
star
37

Rx.NET

Rx.NET – Reactive Extensions for .NET – a library for composing asynchronous and event-based programs using observable sequences for the CLR.
31
star
38

RxQuasar

RxJava bindings for Quasar
Java
16
star
39

RxRoboVM

RxJava bindings for iOS
Java
7
star
40

BuildInfrastructure

Test project for the new build system.
Groovy
5
star
41

RxSwing2

Reactive bindings for Java 8 Swing on top of RxJava 2
4
star