Explore and drive a running JavaFX application from its Clojure REPL.
Calls run synchronously on the JavaFX thread; no Platform/runLater is needed. Input uses synthetic events and works without desktop focus. Application work scheduled by event handlers may finish later.
Start with tree/props to inspect, all/one to find, point to locate, and mouse-click!/key-tap!/key-chord! to interact. Separate press/release functions let you hold keys or buttons across calls.
Inspection accepts a Node, Scene, Window, or synthetic root (called el in signatures). The root contains all open windows. Queries search descendants; tree includes its starting element. Results contain live JavaFX objects. Input accepts a Window, Scene, or synthetic root, never a Node. Omitting the input target requires exactly one open window. Mouse input picks at scene coordinates; keyboard input follows that scene's current focus owner.
Example (p is the alias used throughout these docstrings): (require '[cljfx.plorer :as p]) (p/all javafx.stage.Window) (def window (p/one javafx.stage.Window)) ; assumes one open window (p/tree window :depth 3 :props [:id :text]) (def field (p/one window "#name")) ; replace with a field ID found above (p/mouse-click! window (p/point field 0.5 0.5) :primary) (p/key-tap! window :a) (p/props field :only [:text])
Explore and drive a running JavaFX application from its Clojure REPL. Calls run synchronously on the JavaFX thread; no Platform/runLater is needed. Input uses synthetic events and works without desktop focus. Application work scheduled by event handlers may finish later. Start with tree/props to inspect, all/one to find, point to locate, and mouse-click!/key-tap!/key-chord! to interact. Separate press/release functions let you hold keys or buttons across calls. Inspection accepts a Node, Scene, Window, or synthetic root (called el in signatures). The root contains all open windows. Queries search descendants; tree includes its starting element. Results contain live JavaFX objects. Input accepts a Window, Scene, or synthetic root, never a Node. Omitting the input target requires exactly one open window. Mouse input picks at scene coordinates; keyboard input follows that scene's current focus owner. Example (p is the alias used throughout these docstrings): (require '[cljfx.plorer :as p]) (p/all javafx.stage.Window) (def window (p/one javafx.stage.Window)) ; assumes one open window (p/tree window :depth 3 :props [:id :text]) (def field (p/one window "#name")) ; replace with a field ID found above (p/mouse-click! window (p/point field 0.5 0.5) :primary) (p/key-tap! window :a) (p/props field :only [:text])
(all & args)Return a vector of distinct live elements matching the selectors.
Optional el is a Node, Scene, Window, or synthetic root; omission searches all open windows. Each selector searches descendants of the previous matches, excluding the starting elements. Insert > before a selector to search only direct children. With no selectors, returns [el] (the root if omitted).
Selectors:
Use > and * as unquoted clojure.core functions, not keywords or strings.
(p/all javafx.stage.Window) (p/all window "#form" > ".field") (p/all window {:text "Save"}) (p/all {:fx.plorer/class javafx.stage.Stage :title "My app"}) (p/all window {:id some? :fx.plorer/style-classes #{"primary"}})
See one to require exactly one match, props to discover property keys.
Return a vector of distinct live elements matching the selectors.
Optional el is a Node, Scene, Window, or synthetic root; omission searches
all open windows. Each selector searches descendants of the previous matches,
excluding the starting elements. Insert > before a selector to search only
direct children. With no selectors, returns [el] (the root if omitted).
Selectors:
- Java class: match instances, e.g. javafx.scene.control.Button.
- String: #id, .style-class, or combinations such as #id.primary.large.
- Function or var: predicate on the element. * matches any element.
- Map: all entries must match. Ordinary keys read props; function/var values
are predicates on a property, other values use equality (including sets).
Unsupported properties do not match, even when the expected value is nil.
:fx.plorer/class matches a class, :fx.plorer/pred tests the whole element,
and :fx.plorer/style-classes requires all listed CSS classes.
Use > and * as unquoted clojure.core functions, not keywords or strings.
(p/all javafx.stage.Window)
(p/all window "#form" > ".field")
(p/all window {:text "Save"})
(p/all {:fx.plorer/class javafx.stage.Stage :title "My app"})
(p/all window {:id some? :fx.plorer/style-classes #{"primary"}})
See one to require exactly one match, props to discover property keys.(key-chord! keys)(key-chord! el keys)Press keys in order and release them in reverse order; return nil.
el is a Window, Scene, or synthetic root; omission requires one open window. keys is an ordered collection of javafx.scene.input.KeyCodes or kebab-case keywords. Put modifiers first. Uses the virtual US keyboard; see key-press! for its rules. Use :meta for Command shortcuts on macOS, :control for Ctrl.
The sequence runs on the JavaFX thread in one scene, following its current focus owner. Throws if no focus owner exists; desktop focus is not required. Keys in the chord end released; other held keys retain their state.
(p/key-chord! window [:shift :digit1]) ; type ! (p/key-chord! window [:control :shift :z]) (p/key-chord! window [:meta :a]) ; Command+A
Press keys in order and release them in reverse order; return nil. el is a Window, Scene, or synthetic root; omission requires one open window. keys is an ordered collection of javafx.scene.input.KeyCodes or kebab-case keywords. Put modifiers first. Uses the virtual US keyboard; see key-press! for its rules. Use :meta for Command shortcuts on macOS, :control for Ctrl. The sequence runs on the JavaFX thread in one scene, following its current focus owner. Throws if no focus owner exists; desktop focus is not required. Keys in the chord end released; other held keys retain their state. (p/key-chord! window [:shift :digit1]) ; type ! (p/key-chord! window [:control :shift :z]) (p/key-chord! window [:meta :a]) ; Command+A
(key-press! key)(key-press! el key)Press a virtual US keyboard key; return the focus owner at the press.
el is a Window, Scene, or synthetic root; omission requires one open window. Events follow the scene's current focus owner; throws if none exists. Desktop focus is not required. key is a javafx.scene.input.KeyCode or its kebab-case keyword, e.g. :a, :digit1, :enter, :shift, :control, :meta. Pair with key-release!, or use key-tap!/key-chord! for complete sequences.
Virtual keyboard behavior (independent of host layout and locale):
Letters type lowercase; Shift uppercases them. :caps toggles Caps Lock for letters, with Shift reversing it. Digits and punctuation use US Shift pairs, e.g. :digit1 -> 1/!, :minus -> -/_, :slash -> /?.
Printable keys emit KEY_PRESSED then KEY_TYPED, except while Control, Alt, or Meta is held. Navigation, function, modifier, Enter, and Tab keys emit no typed text. Unmapped keys still emit press/release events.
Numpad digits and arithmetic keys always type their numeric characters. Num Lock, Alt/Option character mappings, dead keys, and IME are not simulated.
Held keys and Caps Lock are tracked per scene. Repeated presses repeat input; a held Caps Lock key toggles only once. There is no repeat timer.
(p/key-press! window :shift) (p/mouse-click! window [50 50] :primary) (p/key-release! window :shift)
Press a virtual US keyboard key; return the focus owner at the press. el is a Window, Scene, or synthetic root; omission requires one open window. Events follow the scene's current focus owner; throws if none exists. Desktop focus is not required. key is a javafx.scene.input.KeyCode or its kebab-case keyword, e.g. :a, :digit1, :enter, :shift, :control, :meta. Pair with key-release!, or use key-tap!/key-chord! for complete sequences. Virtual keyboard behavior (independent of host layout and locale): - Letters type lowercase; Shift uppercases them. :caps toggles Caps Lock for letters, with Shift reversing it. Digits and punctuation use US Shift pairs, e.g. :digit1 -> 1/!, :minus -> -/_, :slash -> /?. - Printable keys emit KEY_PRESSED then KEY_TYPED, except while Control, Alt, or Meta is held. Navigation, function, modifier, Enter, and Tab keys emit no typed text. Unmapped keys still emit press/release events. - Numpad digits and arithmetic keys always type their numeric characters. Num Lock, Alt/Option character mappings, dead keys, and IME are not simulated. - Held keys and Caps Lock are tracked per scene. Repeated presses repeat input; a held Caps Lock key toggles only once. There is no repeat timer. (p/key-press! window :shift) (p/mouse-click! window [50 50] :primary) (p/key-release! window :shift)
(key-release! key)(key-release! el key)Release a virtual key; return the focus owner at the release.
el is a Window, Scene, or synthetic root; omission requires one open window. key is a javafx.scene.input.KeyCode or kebab-case keyword such as :shift. Release follows the scene's current focus owner, which may differ from the press target. Throws if there is no focus owner; desktop focus is not required.
Emits KEY_RELEASED with the text from the key's last press, or empty text if it was not pressed. Clears the released key's modifier flag before dispatch. See key-press! for virtual keyboard rules; use key-tap! for a complete tap.
(p/key-release! window :shift)
Release a virtual key; return the focus owner at the release. el is a Window, Scene, or synthetic root; omission requires one open window. key is a javafx.scene.input.KeyCode or kebab-case keyword such as :shift. Release follows the scene's current focus owner, which may differ from the press target. Throws if there is no focus owner; desktop focus is not required. Emits KEY_RELEASED with the text from the key's last press, or empty text if it was not pressed. Clears the released key's modifier flag before dispatch. See key-press! for virtual keyboard rules; use key-tap! for a complete tap. (p/key-release! window :shift)
(key-tap! key)(key-tap! el key)Press and release one key; return the focus owner at the release.
el is a Window, Scene, or synthetic root; omission requires one open window. key is a javafx.scene.input.KeyCode or kebab-case keyword, e.g. :a, :enter, :tab, :escape, :digit1, :space. Uses a virtual US layout: printable keys type text, Shift/Caps Lock affect case, and Control/Alt/Meta suppress typed text. See key-press! for full keyboard rules and key-chord! for combinations.
Both events run on the JavaFX thread in the same scene, following its current focus owner (which can change after Tab). Throws if no focus owner exists; desktop focus is not required.
(p/key-tap! :enter) (p/key-tap! window :a)
Press and release one key; return the focus owner at the release. el is a Window, Scene, or synthetic root; omission requires one open window. key is a javafx.scene.input.KeyCode or kebab-case keyword, e.g. :a, :enter, :tab, :escape, :digit1, :space. Uses a virtual US layout: printable keys type text, Shift/Caps Lock affect case, and Control/Alt/Meta suppress typed text. See key-press! for full keyboard rules and key-chord! for combinations. Both events run on the JavaFX thread in the same scene, following its current focus owner (which can change after Tab). Throws if no focus owner exists; desktop focus is not required. (p/key-tap! :enter) (p/key-tap! window :a)
(mouse-click! position button)(mouse-click! el position button)Press and release a mouse button at one position; return the release target or nil.
el is a Window, Scene, or synthetic root; omission requires one open window. The scene must be in a showing window; desktop focus is not required. position is a vector [x y] in scene logical pixels from the content area's top-left, excluding window decorations. Use point to locate a node. button is :primary, :middle, :secondary, or a javafx.scene.input.MouseButton.
Both events run on the JavaFX thread in the same scene. JavaFX picks the target at the position, with any held virtual keyboard modifiers applied.
(p/mouse-click! [50 50] :primary) (p/mouse-click! window (p/point node 0.5 0.5) :primary)
Press and release a mouse button at one position; return the release target or nil. el is a Window, Scene, or synthetic root; omission requires one open window. The scene must be in a showing window; desktop focus is not required. position is a vector [x y] in scene logical pixels from the content area's top-left, excluding window decorations. Use point to locate a node. button is :primary, :middle, :secondary, or a javafx.scene.input.MouseButton. Both events run on the JavaFX thread in the same scene. JavaFX picks the target at the position, with any held virtual keyboard modifiers applied. (p/mouse-click! [50 50] :primary) (p/mouse-click! window (p/point node 0.5 0.5) :primary)
(mouse-press! position button)(mouse-press! el position button)Press a mouse button at position [x y]; return the event target or nil.
el is a Window, Scene, or synthetic root; omission requires one open window. The scene must be in a showing window; desktop focus is not required. position is a vector of two finite numbers in scene logical pixels, measured from the content area's top-left (excluding window decorations). button is :primary, :middle, :secondary, or a javafx.scene.input.MouseButton.
JavaFX picks the target at the position. Held virtual keyboard modifiers apply. Pair with mouse-release!, or use mouse-click! for a complete click. point converts a relative position within a node to scene coordinates.
(p/mouse-press! window (p/point node 0.5 0.5) :primary)
Press a mouse button at position [x y]; return the event target or nil. el is a Window, Scene, or synthetic root; omission requires one open window. The scene must be in a showing window; desktop focus is not required. position is a vector of two finite numbers in scene logical pixels, measured from the content area's top-left (excluding window decorations). button is :primary, :middle, :secondary, or a javafx.scene.input.MouseButton. JavaFX picks the target at the position. Held virtual keyboard modifiers apply. Pair with mouse-release!, or use mouse-click! for a complete click. point converts a relative position within a node to scene coordinates. (p/mouse-press! window (p/point node 0.5 0.5) :primary)
(mouse-release! position button)(mouse-release! el position button)Release a mouse button at position [x y]; return the event target or nil.
el is a Window, Scene, or synthetic root; omission requires one open window. The scene must be in a showing window; desktop focus is not required. position is a vector of two finite numbers in scene logical pixels from the content area's top-left. button is :primary, :middle, :secondary, or a javafx.scene.input.MouseButton. Use point to obtain coordinates from a node.
JavaFX keeps the press target through release, even at a different position. Use mouse-click! for a press/release pair at one position.
(p/mouse-release! window [50 50] :primary)
Release a mouse button at position [x y]; return the event target or nil. el is a Window, Scene, or synthetic root; omission requires one open window. The scene must be in a showing window; desktop focus is not required. position is a vector of two finite numbers in scene logical pixels from the content area's top-left. button is :primary, :middle, :secondary, or a javafx.scene.input.MouseButton. Use point to obtain coordinates from a node. JavaFX keeps the press target through release, even at a different position. Use mouse-click! for a press/release pair at one position. (p/mouse-release! window [50 50] :primary)
(one & args)Return the single matching live element; throw on zero or multiple matches.
Optional el is a Node, Scene, Window, or synthetic root; omission searches all open windows. Selectors search descendants. Accepts the same selectors as all, including classes, #id/.class strings, property maps, and predicates. See all for chaining and direct-child syntax. Throws IllegalStateException unless exactly one element matches; use all to inspect ambiguous matches.
(p/one javafx.stage.Window) (p/one window "#name")
Return the single matching live element; throw on zero or multiple matches. Optional el is a Node, Scene, Window, or synthetic root; omission searches all open windows. Selectors search descendants. Accepts the same selectors as all, including classes, #id/.class strings, property maps, and predicates. See all for chaining and direct-child syntax. Throws IllegalStateException unless exactly one element matches; use all to inspect ambiguous matches. (p/one javafx.stage.Window) (p/one window "#name")
(point node x y)Return scene coordinates [x y] for a relative position within a node.
x and y must be numbers from 0 to 1 along the node's local layout bounds: 0,0 is top-left; 0.5,0.5 is center; 1,1 is bottom-right. The Node must belong to a Scene. Converts through ancestor transforms and enclosing SubScenes into the outer scene's coordinates, suitable for mouse input.
Reads current geometry on the JavaFX thread. The result is a snapshot; layout changes, clipping, or overlapping nodes can affect what gets clicked. Exact edges may not be pickable; use e.g. 0.95 to aim just inside an edge.
(p/point node 0.5 0.5) (p/mouse-click! window (p/point node 0.25 0.5) :primary)
Return scene coordinates [x y] for a relative position within a node. x and y must be numbers from 0 to 1 along the node's local layout bounds: 0,0 is top-left; 0.5,0.5 is center; 1,1 is bottom-right. The Node must belong to a Scene. Converts through ancestor transforms and enclosing SubScenes into the outer scene's coordinates, suitable for mouse input. Reads current geometry on the JavaFX thread. The result is a snapshot; layout changes, clipping, or overlapping nodes can affect what gets clicked. Exact edges may not be pickable; use e.g. 0.95 to aim just inside an edge. (p/point node 0.5 0.5) (p/mouse-click! window (p/point node 0.25 0.5) :primary)
(props el & {:keys [only]})Return a map of supported property values for el (a JavaFX element).
With no :only, discover all supported keys. :only selects keys to read; unsupported keys are omitted, while supported keys with nil values remain. Keys are kebab-case names from JavaFX property accessors and observable-list getters, e.g. :text, :id, :style-class. Values can include live JavaFX objects.
(p/props node) (p/props node :only [:id :text :visible])
Return a map of supported property values for el (a JavaFX element). With no :only, discover all supported keys. :only selects keys to read; unsupported keys are omitted, while supported keys with nil values remain. Keys are kebab-case names from JavaFX property accessors and observable-list getters, e.g. :text, :id, :style-class. Values can include live JavaFX objects. (p/props node) (p/props node :only [:id :text :visible])
(tree & args)Return a nested map describing el and its children.
el may be a Node, Scene, Window, or synthetic root. Omit it to inspect all open windows under that root. Each entry has :el (the live object) and a vector of :children. :props adds a property map; see props for supported keys. :depth limits child traversal: 0 omits :children, 1 includes immediate children, and omission traverses the full subtree.
Traversal follows windows to scenes to scene roots, then node children; SubScenes contribute their roots. Start with a small depth to limit output.
(p/tree :depth 2 :props [:title :id]) (p/tree window :depth 3 :props [:id :text]) ;; entry shape: {:el node :props {:id "name"} :children [...]}
Return a nested map describing el and its children.
el may be a Node, Scene, Window, or synthetic root. Omit it to inspect all
open windows under that root. Each entry has :el (the live object) and a
vector of :children. :props adds a property map; see props for supported keys.
:depth limits child traversal: 0 omits :children, 1 includes immediate
children, and omission traverses the full subtree.
Traversal follows windows to scenes to scene roots, then node children;
SubScenes contribute their roots. Start with a small depth to limit output.
(p/tree :depth 2 :props [:title :id])
(p/tree window :depth 3 :props [:id :text])
;; entry shape: {:el node :props {:id "name"} :children [...]}cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |