{"id":13777991,"url":"https://github.com/ReactiveX/RxJavaFX","last_synced_at":"2025-05-11T11:34:36.827Z","repository":{"id":19834613,"uuid":"23095976","full_name":"ReactiveX/RxJavaFX","owner":"ReactiveX","description":"RxJava bindings for JavaFX","archived":false,"fork":false,"pushed_at":"2021-09-09T01:55:23.000Z","size":586,"stargazers_count":517,"open_issues_count":18,"forks_count":66,"subscribers_count":31,"default_branch":"2.11.x","last_synced_at":"2024-06-11T18:41:39.338Z","etag":null,"topics":["java","javafx","reactivex","rxjava"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ReactiveX.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-19T03:47:39.000Z","updated_at":"2024-05-24T01:19:59.000Z","dependencies_parsed_at":"2022-08-23T22:40:26.284Z","dependency_job_id":null,"html_url":"https://github.com/ReactiveX/RxJavaFX","commit_stats":null,"previous_names":[],"tags_count":62,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveX%2FRxJavaFX","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveX%2FRxJavaFX/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveX%2FRxJavaFX/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveX%2FRxJavaFX/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ReactiveX","download_url":"https://codeload.github.com/ReactiveX/RxJavaFX/tar.gz/refs/heads/2.11.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253559679,"owners_count":21927655,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","javafx","reactivex","rxjava"],"created_at":"2024-08-03T18:00:50.330Z","updated_at":"2025-05-11T11:34:36.519Z","avatar_url":"https://github.com/ReactiveX.png","language":"Java","readme":"![](http://i.imgur.com/x7rmXke.png)\n\n# RxJavaFX: JavaFX bindings for RxJava\n\n# NOTE: UNSUPPORTED, PLEASE FOLLOW FORKS FOR NEWER DEVELOPMENTS AND DEPLOYMENTS\nhttps://github.com/torakiki/RxJavaFX\n\n\nRead the free eBook [_Learning RxJava with JavaFX_](https://www.gitbook.com/book/thomasnield/rxjavafx-guide/details) to get started.\n\nRxJavaFX is a lightweight library to convert JavaFX events into [RxJava](https://github.com/ReactiveX/RxJava) Observables/Flowables and vice versa. It also has a `Scheduler` to safely move emissions to the JavaFX Event Dispatch Thread. \n\n**NOTE**: To use with [Kotlin](http://kotlinlang.org/), check out [RxKotlinFX](https://github.com/thomasnield/RxKotlinFX) to leverage this library with extension functions and additional operators. \n\n## Master Build Status\n\n\u003ca href='https://travis-ci.org/ReactiveX/RxJavaFX/builds'\u003e\u003cimg src='https://travis-ci.org/ReactiveX/RxJavaFX.svg?branch=2.11.x'\u003e\u003c/a\u003e\n\n## Documentation\n\n[Learning RxJava with JavaFX](https://www.gitbook.com/book/thomasnield/rxjavafx-guide/details) - Free eBook that covers RxJava from a JavaFX perspective.\n\n[Learning RxJava](https://www.packtpub.com/application-development/learning-rxjava) - Packt book covering RxJava 2.0 in depth, with a few RxJavaFX examples.\n\n[![](https://dz13w8afd47il.cloudfront.net/sites/default/files/imagecache/ppv4_main_book_cover/9781787120426.jpg)](https://www.packtpub.com/application-development/learning-rxjava)\n\n## 1.x Binaries\n\nBinaries and dependency information for Maven, Ivy, Gradle and others can be found at [http://search.maven.org](http://search.maven.org/#search%7Cga%7C1%7Cio.reactivex.rxjavafx).\n\nExample for Maven:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.reactivex\u003c/groupId\u003e\n    \u003cartifactId\u003erxjavafx\u003c/artifactId\u003e\n    \u003cversion\u003e1.x.y\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nGradle: \n\n```groovy \ndependencies {\n\tcompile 'io.reactivex:rxjavafx:1.x.y'\n}\n```\n\n\n## 2.x Binaries\n\nRxJavaFX 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](http://search.maven.org/#search%7Cga%7C1%7Cio.reactivex.rxjava2.rxjavafx).\n\nExample for Maven:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.reactivex.rxjava2\u003c/groupId\u003e\n    \u003cartifactId\u003erxjavafx\u003c/artifactId\u003e\n    \u003cversion\u003e2.x.y\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nGradle: \n\n```groovy \ndependencies {\n\tcompile 'io.reactivex.rxjava2:rxjavafx:2.x.y'\n}\n```\n\n\n\n\n## Features\n\nRxJavaFX has a comprehensive set of features to interop RxJava with JavaFX:\n- Factories to turn `Node`, `ObservableValue`, `ObservableList`, and other component events into an RxJava `Observable`\n- Factories to turn an RxJava `Observable` or `Flowable` into a JavaFX `Binding`. \n- A scheduler for the JavaFX dispatch thread\n\n### Node Events\nYou 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`. \n\n```java\nButton incrementBttn = new Button(\"Increment\");\n\nObservable\u003cActionEvent\u003e bttnEvents =\n        JavaFxObservable.eventsOf(incrementBttn, ActionEvent.ACTION);\n```\n\n### Action Events\nAction 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. \n\nTherefore, a few overloaded factories are provided to emit `ActionEvent` items from these controls\n\n##### Button ActionEvents\n```java\nButton incrementBttn = new Button(\"Increment\");\n\nObservable\u003cActionEvent\u003e bttnEvents =\n        JavaFxObservable.actionEventsOf(incrementBttn);\n```\n##### MenuItem ActionEvents\n```java\nMenuItem menuItem = new MenuItem(\"Select me\");\n\nObservable\u003cActionEvent\u003e menuItemEvents = \n        JavaFxObservable.actionEventsOf(menuItem);\n```\n\n### Other Event Factories\n\nThere 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. \n\n#### Dialogs and Alerts\n```java\nAlert alert = new Alert(AlertType.CONFIRMATION);\nalert.setTitle(\"Confirmation\");\nalert.setHeaderText(\"Please confirm your action\");\nalert.setContentText(\"Are you ok with this?\");\n\nJavaFxObservable.fromDialog(alert)\n    .filter(response -\u003e response.equals(ButtonType.OK))\n    .subscribe(System.out::println,Throwable::printStackTrace);\n```\n\n##### Emitting Scene Events\n\n```java\nObservable\u003cMouseEvent\u003e sceneMouseMovements =\n     JavaFxObservable.eventsOf(scene, MouseEvent.MOUSE_MOVED);\n\nsceneMouseMovements.subscribe(v -\u003e System.out.println(v.getSceneX() + \",\" + v.getSceneY()));\n```\n\n##### Emitting Window Hiding Events\n```java\n Observable\u003cWindowEvent\u003e windowHidingEvents =\n    JavaFxObservable.eventsOf(primaryStage,WindowEvent.WINDOW_HIDING);\n\nwindowHidingEvents.subscribe(v -\u003e System.out.println(\"Hiding!\"));\n```\n\n### ObservableValue \nNot 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. \n\n```java\nTextField textInput = new TextField();\n\nObservable\u003cString\u003e textInputs =\n        JavaFxObservable.valuesOf(textInput.textProperty());\n```\nNote 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. \n\n##### ObservableValue Changes\n\nFor 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. \n\n```java\nSpinnerValueFactory\u003cInteger\u003e svf = new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 100);\nSpinner spinner = new Spinner\u003c\u003e();\nspinner.setValueFactory(svf);\nspinner.setEditable(true);\n\nLabel spinnerChangesLabel = new Label();\nSubscription subscription = JavaFxObservable.changesOf(spinner.valueProperty())\n        .map(change -\u003e \"OLD: \" + change.getOldVal() + \" NEW: \" + change.getNewVal())\n        .subscribe(spinnerChangesLabel::setText);\n```\n\n### ObservableList, ObservableMap, and ObservableSet\n\nThere 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. \n\n\n|Factory Method|Parameter Type|Return Type|Description|\n|---|---|---|---\n|emitOnChanged()|ObservableList\u0026lt;T\u003e|Observable\u0026lt;ObservableList\u0026lt;T\u003e\u003e|Emits the entire `ObservableList` every time it changes|\n|additionsOf()|ObservableList\u0026lt;T\u003e|Observable\u0026lt;T\u003e|Emits additions to an `ObservableList`|\n|removalsOf()|ObservableList\u0026lt;T\u003e|Observable\u0026lt;T\u003e|Emits removals from an `ObservableList`|\n|updatesOf()|ObservableList\u0026lt;T\u003e|Observable\u0026lt;ListChange\u0026lt;T\u003e\u003e|Emits every item that was the result of a change to an `ObservableList`, with an `ADDED`, `REMOVED`, or `UPDATED` flag|\n|distinctChangesOf()|ObservableList\u0026lt;T\u003e| Observable\u0026lt;ListChange\u0026lt;R\u003e\u003e|Emits only *distinct* addtions and removals to an `ObservableList`|\n|distinctMappingsOf()|ObservableList\u0026lt;T\u003e, Func1\u0026lt;T,R\u003e| Observable\u0026lt;ListChange\u0026lt;R\u003e\u003e|Emits only *distinct* additions and removals to an `ObservableList` and emits the mapping|\n|distinctChangesOf()|ObservableList\u0026lt;T\u003e, Func1\u0026lt;T,R\u003e| Observable\u0026lt;ListChange\u0026lt;R\u003e\u003e|Emits only *distinct* additions and removals to an `ObservableList` based on a mapping|\n|emitOnChanged()|ObservableMap\u0026lt;K,T\u003e|Observable\u0026lt;ObservableMap\u0026lt;K,T\u003e\u003e|Emits the entire `ObservableMap` every time it changes|\n|additionsOf()|ObservableMap\u0026lt;K,T\u003e|Observable\u0026lt;Map.Entry\u0026lt;K,T\u003e\u003e|Emits every `Map.Entry\u003cK,T\u003e` added to an `ObservableMap`|\n|removalsOf()|ObservableMap\u0026lt;K,T\u003e|Observable\u0026lt;Map.Entry\u0026lt;K,T\u003e\u003e|Emits every `Map.Entry\u003cK,T\u003e` removed from an `ObservableMap`|\n|changesOf()|ObservableMap\u0026lt;K,T\u003e|Observable\u0026lt;MapChange\u0026lt;K,T\u003e\u003e|Emits every key/value pair with an `ADDED` or `REMOVED` flag.|\n|emitOnChanged()|ObservableSet\u0026lt;T\u003e|Observable\u0026lt;ObservableSet\u0026lt;T\u003e\u003e|Emits the entire `ObservableSet` every time it changes|\n|additionsOf()|ObservableSet\u0026lt;T\u003e|Observable\u0026lt;T\u003e|Emits every addition to an `ObservableSet`|\n|removalsOf()|ObservableSet\u0026lt;T\u003e|Observable\u0026lt;T\u003e|Emits every removal to an `ObservableSet`|\n|changesOf()|ObservableSet\u0026lt;T\u003e|Observable\u0026lt;SetChange\u0026lt;T\u003e|Emits every item `ADDED` or `REMOVED` item from an `ObservableSet` with the corresponding flag|\n\n\n### Binding\nYou 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. \n\n```java\nButton incrementBttn = new Button(\"Increment\");\nLabel incrementLabel =  new Label(\"\");\n\nObservable\u003cActionEvent\u003e bttnEvents =\n        JavaFxObservable.eventsOf(incrementBttn, ActionEvent.ACTION);\n        \nObservable\u003cString\u003e accumulations = bttnEvents.map(e -\u003e 1)\n        .scan(0,(x, y) -\u003e x + y)\n        .map(Object::toString);\n        \nBinding\u003cString\u003e binding = JavaFxObserver.toBinding(accumulations);\n\nincrementLabel.textProperty().bind(binding);\n\n//do stuff, then dispose Binding\nbinding.dispose();\n\n```\n\nIt 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. \n\n```\nincrementLabel.textProperty().bind(binding, e -\u003e e.printStackTrace());\n```\n\n\n### Lazy Binding\n\nThe `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. \n\n```java\nBinding\u003cString\u003e lazyBinding = JavaFxObserver.toLazyBinding(myObservable);\n```\nThis 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. \n\n### CompositeBinding\n\nYou also have the option to use a `CompositeBinding` to group multiple `Binding`s together, and `dispose()` them all at once. It is the JavaFX equivalent to `CompositeSubscription`. \n\n```java\nBinding\u003cLong\u003e binding1 = ...\nbindings.add(binding1);\n\nBinding\u003cLong\u003e binding2 = ... \nbindings.add(binding2);\n\n//do stuff on UI, and dispose() both bindings\nbindings.dispose();\n```        \n\n### JavaFX Scheduler\n\nWhen 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`.\n\n```java\nTextField textInput = new TextField();\nLabel fippedTextLabel = new Label();\n\nObservable\u003cString\u003e textInputs =\n        JavaFxObservable.valuesOf(textInput.textProperty());\n\nsub2 = textInputs.observeOn(Schedulers.computation())\n        .map(s -\u003e new StringBuilder(s).reverse().toString())\n        .observeOn(JavaFxScheduler.platform())\n        .subscribe(fippedTextLabel::setText);\n```\n\n### JavaFX Interval\n\nThere 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`. \n\n```java\nObservable\u003cLong\u003e everySecond = JavaFxObservable.interval(Duration.millis(1000));\n```\n\n## Differences from ReactFX\n[ReactFX](https://github.com/TomasMikula/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. \n\nAlthough 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.\n\nIf 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. \n\n## Notes for Kotlin \nIf you are building your JavaFX application with [Kotlin](https://kotlinlang.org/), check out [RxKotlinFX](https://github.com/thomasnield/RxKotlinFX) to leverage this library through Kotlin extension functions.\n\n## Bugs and Feedback\n\nFor bugs, questions and discussions please use the [Github Issues](https://github.com/ReactiveX/RxJavaFX/issues).\n\n \n## LICENSE\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","funding_links":[],"categories":["Java","Libraries, Tools and Projects"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FReactiveX%2FRxJavaFX","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FReactiveX%2FRxJavaFX","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FReactiveX%2FRxJavaFX/lists"}