{"id":18024047,"url":"https://github.com/thomasnield/rxkotlinfx","last_synced_at":"2025-08-20T02:32:32.059Z","repository":{"id":57723619,"uuid":"51733111","full_name":"thomasnield/RxKotlinFX","owner":"thomasnield","description":"Kotlin extensions to the RxJavaFX framework","archived":false,"fork":false,"pushed_at":"2021-09-09T02:04:35.000Z","size":153,"stargazers_count":176,"open_issues_count":8,"forks_count":13,"subscribers_count":11,"default_branch":"2.x","last_synced_at":"2024-12-06T09:33:58.379Z","etag":null,"topics":["interoperability","javafx","kotlin","kotlin-extensions","reactivex","rxjava","tornadofx"],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","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/thomasnield.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-15T05:34:09.000Z","updated_at":"2024-11-11T06:22:23.000Z","dependencies_parsed_at":"2022-08-29T22:32:24.715Z","dependency_job_id":null,"html_url":"https://github.com/thomasnield/RxKotlinFX","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasnield%2FRxKotlinFX","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasnield%2FRxKotlinFX/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasnield%2FRxKotlinFX/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasnield%2FRxKotlinFX/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thomasnield","download_url":"https://codeload.github.com/thomasnield/RxKotlinFX/tar.gz/refs/heads/2.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230388129,"owners_count":18217755,"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":["interoperability","javafx","kotlin","kotlin-extensions","reactivex","rxjava","tornadofx"],"created_at":"2024-10-30T07:11:47.035Z","updated_at":"2024-12-19T06:08:43.385Z","avatar_url":"https://github.com/thomasnield.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n![](https://camo.githubusercontent.com/78eeb41c5378ae03cf0d23e71c3e0c9e61b0d984/687474703a2f2f692e696d6775722e636f6d2f7837726d586b652e706e67)\n\n# UNSUPPORTED, PLEASE FORK AND SUPPORT\n\n# RxKotlinFX\nKotlin extensions to the [RxJavaFX](https://github.com/ReactiveX/RxJavaFX) library. This framework works especially well with [TornadoFX](https://github.com/edvin/tornadofx). See a fully functional demo [here!](https://github.com/thomasnield/rxkotlinfx-tornadofx-demo)\n\n## Documentation\n[Learning RxJava with JavaFX](https://www.gitbook.com/book/thomasnield/rxjavafx-guide/details)\n\n\n## 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\u003ecom.github.thomasnield\u003c/groupId\u003e\n    \u003cartifactId\u003erxkotlinfx\u003c/artifactId\u003e\n    \u003cversion\u003ex.y.z\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nGradle: \n\n```groovy \nrepositories {\n    mavenCentral()\n}\ndependencies {\n    compile 'com.github.thomasnield:rxkotlinfx:x.y.z'\n}\n```\n## Contributing\nFeel free to contribute and help streamline a pragmatic UI stack with Kotlin, RxJava, and JavaFX. Speaking of stacks, this project may be used in conjunction with [TornadoFX](https://github.com/edvin/tornadofx) and [RxKotlin](https://github.com/ReactiveX/RxKotlin). Please make sure no extension naming conventions conflict with these two other libraries :)\n\n## Features\n\nRxKotlinFX is the convergence of interoperability between [RxJava](https://github.com/ReactiveX/RxJava), [JavaFX](http://docs.oracle.com/javase/8/javase-clienttechnologies.htm), and [Kotlin](https://kotlinlang.org/). \n\n![](http://i.imgur.com/Bhh5CX4.png)\n\nRxKotlinFX contains Kotlin extensions to [RxJavaFX](https://github.com/ReactiveX/RxJavaFX) as well as additional `Observable` operators specific to JavaFX. It also is in exporatory stages to add helpful `Node` extension functions that return Observables. This exploration is inspired by the JavaFX/Kotlin interop project [TornadoFX](https://github.com/edvin/tornadofx). Where TornadoFX handles layouts, node extensions, DI, and other JavaFX/Kotlin interoperations, this library will seek to integrate RxJava with JavaFX in the same spirit using Kotlin. The vision is to add useful extensions that put `Observable` streams as properties and functions on JavaFX components, especially where `ObservableValue` properties are not readily available. \n\n### RxJavaFX Extensions\nThe core API implements [RxJavaFX](https://github.com/ReactiveX/RxJavaFX) static factories as extension functions. \n\n|Target Type|Extension Function|Description|\n|---|---|---\n|Observable\u0026lt;T\u003e|toBinding()|Subscribes the `Observable\u003cT\u003e` to a JavaFX `Binding` implementation. Calling `dispose()` will unsubscribe from the `Observable\u003cT\u003e`\n|Observable\u0026lt;T\u003e|toLazyBinding()|Subscribes the `Observable\u003cT\u003e` to a lazy JavaFX `Binding` implementation, delaying subscription until a value is needed. Calling `dispose()` will unsubscribe from the `Observable\u003cT\u003e`\n|Property\u0026lt;T\u003e|bind(observable: Observable\u0026lt;T\u003e)|Binds a `Property\u003cT\u003e` to the emissions of an `Observable\u003cT\u003e`, and returns the `Binding`\n|Binding\u0026lt;T\u003e|addTo(compositeBinding: CompositeBinding)|Adds the `Binding` to a `CompositeBinding`, and returns the `Binding`\n|ObservableValue\u0026lt;T\u003e|toObservable()|Turns a JavaFX `ObservableValue\u003cT\u003e` into an RxJava `Observable\u003cT\u003e` that emits the latest value\n|ObservableValue\u0026lt;T\u003e|toObservableChanges()|Turns a JavaFX `ObservableValue\u003cT\u003e` into an RxJava `Observable\u003cChange\u003cT\u003e\u003e` that emits the old value and new value as a pair\n|Dialog\u0026lt;T\u003e|toObservable\u0026lt;T\u003e|Returns an `Observable\u003cT\u003e` that emits the given result of `Dialog\u003cT\u003e`. Will be empty if no response. \n|Node, Window,  Scene|events(eventType: EventType\u003cT\u003e)| Creates an `Observable` emitting events of the given `EventType`\n|Node, MenuItem, ContextMenu |actionEvents()|Creates an `Observable` that emits an `ActionEvent` every time one occurs\n|ObservableList\u0026lt;T\u003e|onChangedObservable()|Returns an `Observable\u003cObservableList\u003cT\u003e\u003e` that emits the entire `ObservableList\u003cT\u003e` every time it is modified.\n|ObservableList\u0026lt;T\u003e|additions()|Creates an `Observable\u003cT\u003e` emitting `T` items that were added to the `ObservableList\u003cT\u003e`\n|ObservableList\u0026lt;T\u003e|removals()|Creates an `Observable\u003cT\u003e` emitting `T` items that were removed from the `ObservableList\u003cT\u003e`\n|ObservableList\u0026lt;T\u003e|updates()|Creates an `Observable\u003cT\u003e` emitting `T` items whose specified properties were updated in the `ObservableList\u003cT\u003e`\n|ObservableList\u0026lt;T\u003e|changes()|Creates an `Observable\u003cListChange\u003cT\u003e\u003e` emitting `ListChange\u003cT\u003e` items, which pairs each item with an `ADDED`, `REMOVED`, or `UPDATED` flag\n|ObservableList\u0026lt;T\u003e|distinctChanges()|Creates an `Observable\u003cListChange\u003cT\u003e\u003e` emitting *distinct* `ListChange\u003cT\u003e` items. It  will only emit the first `ADDED` item `T` and not emit dupes, and will only emit the `REMOVED` item `T` when no more dupes exist\n|ObservableList\u0026lt;T\u003e|distinctChanges(mapper: (T) -\u003e R)|Creates an `Observable\u003cListChange\u003cT\u003e\u003e` emitting *distinct* `ListChange\u003cT\u003e` items based off the `mapper`'s definition of a distinct value `R`. It  will only emit the first `ADDED` item `T` and not emit dupes, and will only emit the `REMOVED` item `T` when no more dupes exist\n|ObservableList\u0026lt;T\u003e|distinctMappingChanges(mapper: (T) -\u003e R)|Creates an `Observable\u003cListChange\u003cR\u003e\u003e` emitting *distinct* `ListChange\u003cR\u003e` mappings based off the `mapper`'s definition of a distinct value `R`. It  will only emit the first `ADDED` item `R` and not emit dupes, and will only emit the `REMOVED` item `R` when no more dupes exist\n\n\n##### Observable of Button ActionEvents\n```kotlin\nval myButton = Button(\"Press Me\")\nval subscription = myButton.actionEvents().subscribe { println(\"Pressed!\") } \n```\n##### Creating a Reactive Binding\n```kotlin\nval myButton = Button(\"Press Me\")\n\nval countBinding = myButton.actionEvents().map { 1 }\n    .scan(0, { x,y -\u003e x + y })\n    .map { it.toString() }\n    .toBinding()\n    \nval myLabel = Label()\nmyLabel.textProperty().bind(countBinding)\n```\n\n##### Observable of ObservableList Events\n```kotlin\nval items = FXCollections.observableArrayList(\"Alpha\", \"Beta\", \"Gamma\")\n\nval changes = items.changes()\n\nchanges.filter { it.flag == Flag.ADDED }\n        .map { it.value }\n        .subscribe { println(\"ADDED $it\") }\n\nitems.add(\"Delta\")\nitems.add(\"Epsilon\")\n```\n###### OUTPUT\n```\nADDED Delta\nADDED Epsilon\n```\n\n##### Turning an ObservableList into a Hot Concatenation\n\n```kotlin\nval observableList = FXCollections.observableArrayList\u003cString\u003e()\n\nobservableList.onChangedObservable()\n        .flatMap {\n            it.toObservable().map { it.length }\n                    .map { it.toString() }\n                    .reduce { s1,s2 -\u003e s1 + \"|\"  + s2  }\n        }\n        .subscribe { println(it) }\n\nobservableList.setAll(\"Alpha\", \"Beta\", \"Gamma\")\nobservableList.add(\"Delta\")\nobservableList.add(\"Epsilon\")\nobservableList.remove(\"Alpha\")\n\n```\n###### OUTPUT\n```\n5|4|5\n5|4|5|5\n5|4|5|5|7\n4|5|5|7\n```\n\n##### Using a Dialog or Alert\n\n```kotlin\nval dialog = Alert(AlertType.CONFIRMATION, \"Are you sure you want to continue?\")\n\ndialog.toObservable().filter { it == ButtonType.YES }\n\t.subscribe { println(\"You pressed YES\") } \n```\n\n##### Using and Disposing CompositeBinding\n```kotlin\nval binding1: Binding = ...\nval binding2: Binding = ... \n\n//adding one at a time\nval bindings = CompositeBinding()\nval bindings += binding1\nval bindings += binding2\n\n//or all at once\nval bindings = CompositeBinding(binding1,binding2)\n\n//do stuff, then dispose Bindings\nbindings.dispose()\n```\n\n\n### Operators\nRxKotlinFX has a growing list of operators placed as extension functions onto `Observable` that aid interoperability with JavaFX.\n\n|Operator|Description|\n|----|-----|\n|observeOnFx()|Schedules the emissions to be observed on the JavaFX thread\n|subscribeOnFx()|Schedules the source `Observable` to emit items on the JavaFX thread\n|doOnNextFx()|Executes the specified action on the FX thread for each emission\n|doOnErrorFx()|Executes the specified action on the FX thread when an error is emitted\n|doOnCompleteFx()|Executes the specified action on the FX thread when the `Observable` calls `onComplete()`\n|doOnSubscribeFx()|Executes the specified action on the FX thread when the `Observable` is first subscribed\n|doOnTerminateFx()|Executes the specified action on the FX thread when the `Observable` calls `onComplete()` or `onError()`\n|doOnDisposeFx()|Executes the specified action on the FX thread when the `Observable` is unsubscribed\n|doOnNextCount()|Executes the specified action with the cumulative count of emissions for that emission\n|doOnErrorCount()|Executes the specified action with the cumulative count of emissions when an error is emitted\n|doOnCompleteCount()|Executes the specified action with the total emission count when `onComplete()` is called\n|doOnNextCountFx()|Same as `doOnNextCount()` except action is executed on FX thread\n|doOnErrorCountFx()|Same as `doOnErrorCount()` except action is executed on FX thread\n|doOnCompleteCountFx()|Same as `doOnCompleteCount()` except action is executed on FX thread\n\nThe `doOnXXXCount()` operators are especially helpful for providing a status update of how many items have been \"processed\" by an `Observable`. \n\n```kotlin\nval source = Observable.range(1,1000)\nval processedCountLabel = Label()\n\nsource.map { it * 10 }\n     .doOnNextFx { processedCountLabel.text = \"Processed $it items\" }\n     .subsribe { doSomethingWith(it) }\n```\n\n### Control Extensions\nThe rest of the project will likely add convenient extension functions to emit events as `Observable` values, [much like the TornadoFX project has done](https://github.com/edvin/tornadofx/blob/master/src/main/java/tornadofx/Nodes.kt). For example, helpful `Observable` extension functions and properties can be added to `TableView` and `ListView`, such as selection events.\n\n```kotlin\nval tableView: TableView\u003cMyItem\u003e = ...\nval selections: Observable\u003cMyItem\u003e = tableView.itemSelections\nval rowIndexSelections: Observable\u003cInt\u003e = tableView.rowIndexSelections\n```\n\nCheck releases as well the [Nodes code file](https://github.com/thomasnield/RxKotlinFX/blob/master/src/main/kotlin/rx/javafx/kt/Nodes.kt) to see a list of available extensions. Feel free to contribute if you see any missing.\n\n\n## Bugs and Feedback\n\nFor bugs, questions and discussions please use the [Github Issues](https://github.com/thomasnield/RxKotlinFx/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\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasnield%2Frxkotlinfx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomasnield%2Frxkotlinfx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasnield%2Frxkotlinfx/lists"}