{"id":13801351,"url":"https://github.com/aaronc/fx-clj","last_synced_at":"2025-08-20T00:40:20.554Z","repository":{"id":20499863,"uuid":"23778286","full_name":"aaronc/fx-clj","owner":"aaronc","description":"A Clojure library for JavaFX","archived":false,"fork":false,"pushed_at":"2018-05-22T09:59:37.000Z","size":485,"stargazers_count":108,"open_issues_count":11,"forks_count":9,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-02-27T21:37:09.561Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://documentup.com/aaronc/fx-clj","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aaronc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-09-08T03:40:17.000Z","updated_at":"2024-07-27T07:21:35.000Z","dependencies_parsed_at":"2022-08-30T17:51:58.550Z","dependency_job_id":null,"html_url":"https://github.com/aaronc/fx-clj","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronc%2Ffx-clj","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronc%2Ffx-clj/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronc%2Ffx-clj/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronc%2Ffx-clj/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aaronc","download_url":"https://codeload.github.com/aaronc/fx-clj/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243852485,"owners_count":20358271,"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":[],"created_at":"2024-08-04T00:01:21.885Z","updated_at":"2025-03-17T08:37:13.802Z","avatar_url":"https://github.com/aaronc.png","language":"Clojure","funding_links":[],"categories":["GUI"],"sub_categories":[],"readme":"**[Guide](http://documentup.com/aaronc/fx-clj)** | **[API docs](http://aaronc.github.io/fx-clj/)** | **[Source](http://github.com/aaronc/fx-clj)** | **[CHANGELOG](https://github.com/aaronc/fx-clj/releases)** | **[License](https://raw.githubusercontent.com/aaronc/fx-clj/master/LICENSE)**\n\n[![Clojars Project](http://clojars.org/fx-clj/latest-version.svg)](http://clojars.org/fx-clj)\n\nBeta quality - the API is pretty stable and has gotten a fair amount of testing. JDK 8 and at least Clojure 1.7.0-alpha3 are required.\n\n## Overview\n\nA Clojure library for JavaFX 8 with the following goals:\n\n- Provide convenience functions for creating and modifying JavaFX\n  objects without attempting to completely hide the JavaFX API\n- Work with **core.async** out of the box\n- Provide support for creating JavaFX objects with both a function\n  based - `(fx/h-box (fx/button \"Hello World\"))` - and **hiccup-like** API -\n  `(fx/compile-fx [:h-box [:button \"Hello World\"]])`.\n- Provide an API for modifying nodes with selectors (sort of like enlive) **for interacting with\n  FXML resources**\n- Allow for setting JavaFX CSS from code and integrate with the **garden CSS**\n  library\n- Helper functions for **i18n**\n- Provide **data binding to reactive atoms, cursors and expressions** (via [freactive.core](https://github.com/aaronc/freactive.core)).\n\n## Quick Start\n\nMake sure you have installed [JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) and have lein configured to use it. See the leiningen [sample.project.clj](https://github.com/technomancy/leiningen/blob/master/sample.project.clj) and search for `LEIN_JAVA_CMD`, `:java-cmd` and `JAVA_CMD` to see different ways to do this.\n\nAdd the leiningen dependency to your project listed above and a namespace declaration similar to the following to your code:\n\n```clojure\n(ns my-ns\n  (:require [fx-clj.core :as fx]))\n```\n\nA \"hello world\" example:\n```clojure\n(ns example\n  (:require [fx-clj.core :as fx]))\n\n(defn create-view []\n  (fx/h-box\n    (fx/button {:on-action (fn [e] (println \"Hello World!\"))\n                :text \"Click Me!\"})))\n\n(fx/sandbox #'create-view) ;; Creates a \"sandbox\" JavaFX window to\n                           ;; show the view. Clicking F5 in this\n                           ;; window will refresh the view allowing the\n                           ;; create-view function to be updated at the REPL\n\n```\n\nA quick example for integrating `fx-clj` and `core.async`:\n```clojure\n(ns example2\n  (:require [fx-clj.core :as fx])\n  (:require [clojure.core.async :refer [chan go \u003c! \u003e!]]))\n\n(defn create-view []\n  (let [click-ch (chan)\n        btn (fx/button :#my-btn {:on-action click-ch ;; You can bind a core.async channel directly to an event\n                        :text \"Next\"})\n\n        txt (fx/text \"Initial text\")\n        view (fx/v-box txt btn)]\n        \n    (go\n      (\u003c! click-ch)\n      (fx/run\u003c! (fx/pset! txt \"Next text\"))\n      (\u003c! click-ch)\n      (fx/run\u003c!\n        (fx/pset! txt \"Last text\")\n        (fx/pset! btn {:text \"Done\"}))\n      (println \"Done listening to clicks\"))\n\n    view))\n\n(fx/sandbox #'create-view)\n```\n\n## Usage\n\n### Interacting with the JavaFX application thread\n\nThere are three macros for interacting with the JavaFX application\nthread - each providing slightly different asynchronous behavior:\n`run!`, `run\u003c!` and `run\u003c!!`. For those familiar with core.async, these\ncorrespond to the behavior of `put!`, `\u003c!` and `\u003c!!`\nrespectively.\n\n`run!` sends a block of code to be run asynchronously on the JavaFX\napplication thread without blocking the caller. (It is effectively a\nthin wrapper around javafx.application.Platform/runLater.)\n\n```clojure\n(run! (do-something)) ;; run asynchously without blocking\n```\n\n`run\u003c!` *can only be used in a core.async* `go` *block!* It uses a\ncore.async channel and `\u003c!` to return the value of the code executed\non the JavaFX application thread to the caller in the `go` block. (This\nblocks the `go` block, but does not block a thread.)\n\n```clojure\n(go\n    (let [res (run\u003c! (do-something))] ;; Go block paused\n        (println res)))\n```\n\n`run\u003c!!` uses a core.async channel and `\u003c!!` to return the value of\nthe code executed on the JavaFX application thread. It blocks the\ncalling thread until the block has completed and returns its value\nto the caller.\n\n```clojure\n(let [res (run\u003c!! (do-something))] ;; Calling thread blocked\n    (println res)))\n```\n\n### Modifying JavaFX objects\n\nThe pset! function is used to modify JavaFX objects.\n\nThe signature for `pset!` is the following:\n\n```clojure\n(defn pset! [element id-class-keyword? property-map? content-or-children*])\n```\n\n`id-class-kw?` (optional): a keyword representing a hiccup style ID and\nclasses (i.e. `:#some-id.some-class.another-class`).\n\n`property-map?` (optional): a map of property keys and setters. Keys can be\nkebab-case keywords corresponding to JavaFX bean properties. Values are\nconverted using `clojurefx.core.convert/convert-arg`. If a value is an\ninstance of ObservableValue (or is converted to one),\nit will be bound to the property.\n\n`content-or-children*` (zero or more): element or elements to be bound to the\nJavaFX element's DefaultProperty. If the DefaultProperty is a list property\nthen multiple children elements can be bound, otherwise only a single\n'content' element can be bound.\n\n### Creating JavaFX objects\n\nThere is both a function-based and hiccup-style API for creating\nJavaFX objects.\n\nSee the API documentation for `fx-clj.core` for a list of\nsupported JavaFX objects.\n\nThe syntax for all object creation functions and the hiccup like\nvectors, is identical to the `pset!` syntax after the first argument (for the target element).\nChoosing between the different styles is basically a matter of preference.\nAll of the following are equivalent:\n\n```clojure\n(fx/button :#my-btn.my-class {:on-action (fn [] (println \"Clicked\"))} \"Click Me\")\n\n(fx/compile-fx [:button#my-btn.my-class {:on-action (fn [] (println \"Clicked\"))}] \"Click Me\")\n\n(fx/pset! (Button.) :#my-btn.my-class {:on-action (fn [] (println \"Clicked\"))} \"Click Me\")\n\n```\n\nBecause the `DefaultProperty` of `Button` is `text`, it can be set by passing a\nsingle argument after the property map.\n\nElements can also be defined using FXML and modified with a selector-based transform (sort of like in enlive) using the `at!` function. Right now only ID-based selectors are supported. `pset!` based transforms are supported as well as a limited number of other transforms. See the [test example](https://github.com/aaronc/fx-clj/blob/master/test/fx_clj/example_enlive.clj).\n\n### Data Binding\n\nThe reactive atoms, expressions and cursors from [freactive.core](https://github.com/aaronc/freactive.core) can be bound to any JavaFX property. Unfortunately not all of this capability is thoroughly documented - see the `fx-clj.core.binding` namespace (which is all pulled into `fx-clj.core` by `potemkin`) for more info.\n\n\n## License\n\nCopyright © 2014 Aaron Craelius\n\nDistributed under the Eclipse Public License either version 1.0 or (at\nyour option) any later version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faaronc%2Ffx-clj","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faaronc%2Ffx-clj","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faaronc%2Ffx-clj/lists"}