fn-fx / fn-fx Goto Github PK
View Code? Open in Web Editor NEWA Functional API around JavaFX / OpenJFX.
License: Eclipse Public License 1.0
A Functional API around JavaFX / OpenJFX.
License: Eclipse Public License 1.0
I run examples/other_examples/todo.clj
with lein run
on mac os sierra, when the window lose focus, the program will exit automatically with no error output.
Apparently needs some updates. Checked the deps
and fiddled with lein
a bit, but can't even get the examples to run.
fn-fx$ java -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
fn-fx$ clj examples/getting_started/01_hello_word.clj
Exception in thread "main" java.lang.ClassNotFoundException: org.reflections.Reflections, compiling:(fn_fx/util/reflect_utils.clj:1:1)
at clojure.lang.Compiler.load(Compiler.java:7526)
at clojure.lang.RT.loadResourceScript(RT.java:379)
at clojure.lang.RT.loadResourceScript(RT.java:370)
at clojure.lang.RT.load(RT.java:460)
at clojure.lang.RT.load(RT.java:426)
at clojure.core$load$fn__6548.invoke(core.clj:6046)
at clojure.core$load.invokeStatic(core.clj:6045)
at clojure.core$load.doInvoke(core.clj:6029)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5848)
at clojure.core$load_one.invoke(core.clj:5843)
at clojure.core$load_lib$fn__6493.invoke(core.clj:5888)
at clojure.core$load_lib.invokeStatic(core.clj:5887)
at clojure.core$load_lib.doInvoke(core.clj:5868)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$load_libs.invokeStatic(core.clj:5925)
at clojure.core$load_libs.doInvoke(core.clj:5909)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$require.invokeStatic(core.clj:5947)
at clojure.core$require.doInvoke(core.clj:5947)
at clojure.lang.RestFn.invoke(RestFn.java:482)
at fn_fx.render_core$eval159$loading__6434__auto____160.invoke(render_core.clj:1)
at fn_fx.render_core$eval159.invokeStatic(render_core.clj:1)
at fn_fx.render_core$eval159.invoke(render_core.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:7062)
at clojure.lang.Compiler.eval(Compiler.java:7051)
at clojure.lang.Compiler.load(Compiler.java:7514)
at clojure.lang.RT.loadResourceScript(RT.java:379)
at clojure.lang.RT.loadResourceScript(RT.java:370)
at clojure.lang.RT.load(RT.java:460)
at clojure.lang.RT.load(RT.java:426)
at clojure.core$load$fn__6548.invoke(core.clj:6046)
at clojure.core$load.invokeStatic(core.clj:6045)
at clojure.core$load.doInvoke(core.clj:6029)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5848)
at clojure.core$load_one.invoke(core.clj:5843)
at clojure.core$load_lib$fn__6493.invoke(core.clj:5888)
at clojure.core$load_lib.invokeStatic(core.clj:5887)
at clojure.core$load_lib.doInvoke(core.clj:5868)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$load_libs.invokeStatic(core.clj:5925)
at clojure.core$load_libs.doInvoke(core.clj:5909)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$require.invokeStatic(core.clj:5947)
at clojure.core$require.doInvoke(core.clj:5947)
at clojure.lang.RestFn.invoke(RestFn.java:436)
at fn_fx.fx_dom$eval153$loading__6434__auto____154.invoke(fx_dom.clj:1)
at fn_fx.fx_dom$eval153.invokeStatic(fx_dom.clj:1)
at fn_fx.fx_dom$eval153.invoke(fx_dom.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:7062)
at clojure.lang.Compiler.eval(Compiler.java:7051)
at clojure.lang.Compiler.load(Compiler.java:7514)
at clojure.lang.RT.loadResourceScript(RT.java:379)
at clojure.lang.RT.loadResourceScript(RT.java:370)
at clojure.lang.RT.load(RT.java:460)
at clojure.lang.RT.load(RT.java:426)
at clojure.core$load$fn__6548.invoke(core.clj:6046)
at clojure.core$load.invokeStatic(core.clj:6045)
at clojure.core$load.doInvoke(core.clj:6029)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5848)
at clojure.core$load_one.invoke(core.clj:5843)
at clojure.core$load_lib$fn__6493.invoke(core.clj:5888)
at clojure.core$load_lib.invokeStatic(core.clj:5887)
at clojure.core$load_lib.doInvoke(core.clj:5868)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$load_libs.invokeStatic(core.clj:5925)
at clojure.core$load_libs.doInvoke(core.clj:5909)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$require.invokeStatic(core.clj:5947)
at clojure.core$require.doInvoke(core.clj:5947)
at clojure.lang.RestFn.invoke(RestFn.java:436)
at getting_started.01_hello_word$eval147$loading__6434__auto____148.invoke(01_hello_word.clj:1)
at getting_started.01_hello_word$eval147.invokeStatic(01_hello_word.clj:1)
at getting_started.01_hello_word$eval147.invoke(01_hello_word.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:7062)
at clojure.lang.Compiler.eval(Compiler.java:7051)
at clojure.lang.Compiler.load(Compiler.java:7514)
at clojure.lang.Compiler.loadFile(Compiler.java:7452)
at clojure.main$load_script.invokeStatic(main.clj:278)
at clojure.main$script_opt.invokeStatic(main.clj:338)
at clojure.main$script_opt.invoke(main.clj:333)
at clojure.main$main.invokeStatic(main.clj:424)
at clojure.main$main.doInvoke(main.clj:387)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:702)
at clojure.main.main(main.java:37)
Caused by: java.lang.ClassNotFoundException: org.reflections.Reflections
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at clojure.lang.DynamicClassLoader.findClass(DynamicClassLoader.java:69)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at clojure.lang.DynamicClassLoader.loadClass(DynamicClassLoader.java:77)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at clojure.lang.RT.classForName(RT.java:2204)
at clojure.lang.RT.classForNameNonLoading(RT.java:2217)
at fn_fx.util.reflect_utils$eval629$loading__6434__auto____630.invoke(reflect_utils.clj:1)
at fn_fx.util.reflect_utils$eval629.invokeStatic(reflect_utils.clj:1)
at fn_fx.util.reflect_utils$eval629.invoke(reflect_utils.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:7062)
at clojure.lang.Compiler.eval(Compiler.java:7051)
at clojure.lang.Compiler.load(Compiler.java:7514)
... 93 more
The constructors of KeyFrame are not being initialized correctly and we just get the default/empty constructor. It should actually have multiple constructor values (:time and :on-finished) https://docs.oracle.com/javase/8/javafx/api/javafx/animation/KeyFrame.html
I've narrowed down the issue a bit. Comparing something that works
(fn-fx.util.reflect-utils/get-value-ctors javafx.scene.image.Image)
output:
({:method #object[java.lang.reflect.Method 0x8876855 "public static javafx.scene.image.Image javafx.scene.image.Image.impl_fromPlatformImage(java.lang.Object)"], :is-ctor? false, :method-name impl_fromPlatformImage, :prop-names (image), :prop-types [java.lang.Object], :prop-names-kw [:image], :prop-names-sym [image]} {:method #object[java.lang.reflect.Constructor 0x49507ef5 "public javafx.scene.image.Image(java.io.InputStream,double,double,boolean,boolean)"], :is-ctor? true, :method-name javafx.scene.image.Image, :prop-names (is requestedWidth requestedHeight preserveRatio smooth), :prop-types [java.io.InputStream double double boolean boolean], :prop-names-kw [:is :requested-width :requested-height :preserve-ratio :smooth], :prop-names-sym [is requested-width requested-height preserve-ratio smooth]} {:method #object[java.lang.reflect.Constructor 0x70df4b07 "public javafx.scene.image.Image(java.io.InputStream)"], :is-ctor? true, :method-name javafx.scene.image.Image, :prop-names (is), :prop-types [java.io.InputStream], :prop-names-kw [:is], :prop-names-sym [is]} {:method #object[java.lang.reflect.Constructor 0x18cdfc45 "public javafx.scene.image.Image(java.lang.String)"], :is-ctor? true, :method-name javafx.scene.image.Image, :prop-names (url), :prop-types [java.lang.String], :prop-names-kw [:url], :prop-names-sym [url]} {:method #object[java.lang.reflect.Constructor 0x2b3bfac9 "public javafx.scene.image.Image(java.lang.String,double,double,boolean,boolean)"], :is-ctor? true, :method-name javafx.scene.image.Image, :prop-names (url requestedWidth requestedHeight preserveRatio smooth), :prop-types [java.lang.String double double boolean boolean], :prop-names-kw [:url :requested-width :requested-height :preserve-ratio :smooth], :prop-names-sym [url requested-width requested-height preserve-ratio smooth]} {:method #object[java.lang.reflect.Constructor 0x61568e8d "public javafx.scene.image.Image(java.lang.String,boolean)"], :is-ctor? true, :method-name javafx.scene.image.Image, :prop-names (url backgroundLoading), :prop-types [java.lang.String boolean], :prop-names-kw [:url :background-loading], :prop-names-sym [url background-loading]} {:method #object[java.lang.reflect.Constructor 0x6bdb66d3 "public javafx.scene.image.Image(java.lang.String,double,double,boolean,boolean,boolean)"], :is-ctor? true, :method-name javafx.scene.image.Image, :prop-names (url requestedWidth requestedHeight preserveRatio smooth backgroundLoading), :prop-types [java.lang.String double double boolean boolean boolean], :prop-names-kw [:url :requested-width :requested-height :preserve-ratio :smooth :background-loading], :prop-names-sym [url requested-width requested-height preserve-ratio smooth background-loading]})
To KeyFrame which is broken
(fn-fx.util.reflect-utils/get-value-ctors javafx.animation.KeyFrame)
output:
({:method #object[java.lang.reflect.Constructor 0x28f769b2 "public javafx.animation.KeyFrame(javafx.util.Duration,javafx.event.EventHandler,javafx.animation.KeyValue[])"], :is-ctor? true, :method-name javafx.animation.KeyFrame, :prop-names (), :prop-types [javafx.util.Duration javafx.event.EventHandler [Ljavafx.animation.KeyValue;], :prop-names-kw [], :prop-names-sym []} {:method #object[java.lang.reflect.Constructor 0x64f9ddf1 "public javafx.animation.KeyFrame(javafx.util.Duration,java.lang.String,javafx.animation.KeyValue[])"], :is-ctor? true, :method-name javafx.animation.KeyFrame, :prop-names (), :prop-types [javafx.util.Duration java.lang.String [Ljavafx.animation.KeyValue;], :prop-names-kw [], :prop-names-sym []} {:method #object[java.lang.reflect.Constructor 0x5002e3ee "public javafx.animation.KeyFrame(javafx.util.Duration,javafx.animation.KeyValue[])"], :is-ctor? true, :method-name javafx.animation.KeyFrame, :prop-names (), :prop-types [javafx.util.Duration [Ljavafx.animation.KeyValue;], :prop-names-kw [], :prop-names-sym []} {:method #object[java.lang.reflect.Constructor 0x35c9f65a "public javafx.animation.KeyFrame(javafx.util.Duration,java.lang.String,javafx.event.EventHandler,javafx.animation.KeyValue[])"], :is-ctor? true, :method-name javafx.animation.KeyFrame, :prop-names (), :prop-types [javafx.util.Duration java.lang.String javafx.event.EventHandler [Ljavafx.animation.KeyValue;], :prop-names-kw [], :prop-names-sym []} {:method #object[java.lang.reflect.Constructor 0x26e0a3a8 "public javafx.animation.KeyFrame(javafx.util.Duration,java.lang.String,javafx.event.EventHandler,java.util.Collection)"], :is-ctor? true, :method-name javafx.animation.KeyFrame, :prop-names (), :prop-types [javafx.util.Duration java.lang.String javafx.event.EventHandler java.util.Collection], :prop-names-kw [], :prop-names-sym []})
It's really hard to see with GitHub's formatting, but there a semi-colon ";" that shows up near the beginning of the KeyFrame output It's very bizarre and makes most of the output effectively commented out.
Running:
(:method (first (fn-fx.util.reflect-utils/get-ctors javafx.animation.KeyFrame)))
Does give us something where we can see the constructor arguments are there
#object[java.lang.reflect.Constructor 0x67dc18da "public javafx.animation.KeyFrame(javafx.util.Duration,javafx.event.EventHandler,javafx.animation.KeyValue[])"]
Past that, I'm not sure. Something is not quite parsing in the values correctly. I haven't been able to figure out the rest of the internals of get-value-ctors
b/c the code is a bit beyond me. Any help would be greatly appreciated
It would be great if the project included a deps.edn
file, so that users of the Clojure command line tools can evaluate the library.
fn-fx should support javafx.scene.web.WebView
With a WebView one needs to call .getEngine().load()
or .getEngine().loadContent()
to do something meaningfull. The problem is that the underlying WebEngine
is not accessible via a property in JavaFX, but more importantly .load()
and .loadContent()
are actions that should happen on an event, and can't be called on each render cycle like the properties.
Ideally the fn-fx's API should support this use case directly. As an alternative solution, fn-fx could have a standard way to access the underlying Java FX objects so that use cases like this are possible.
I want to get the instance of PixelWriter because I want to draw images.
So , I need this function ...
PixelWriter writer = canvas.getGraphicsContext2D().getPixelWriter()
But I don't know how to do it in this api.
I think ...
(defui Image
(render [this]
(controls/canvas
(**something, but I cannot find solution**))))
So, can you give me some example?
@halgari, @pmonks, @roti: I've been staring at the fn-fx.diff/defui code for the longest time and I can't quite figure out what it is doing.
I started on a simplified non-react wrapper for javafx that enables property bindings instead of a virtual dom. It's okay and found that I like the syntax but the app does becomes harder to control the bigger it gets.
So I'm looking deeper into fn-fx. However, I built the javafx wrapper to compile hiccup syntax and I quite like it:
(defn application [state]
(let [output-img (derived-output state)]
(fx/ui [:stage {:title (fx/get state [:window :title] str)
:width (fx/set state [:window :width])}
[:scene
[:border-pane
{:bottom [:label "hello"]
:center [:border-pane
{:center [:anchor-pane
[:image-view
{:fit-width (fx/get state [:window :width] #(- % 300))
:preserve-ratio true
:image (fx/get output-img [])}]])}]
:right (cp/control-pane state)}]]]))
What I'm looking to do is to modify fn-fx slightly to get this type of syntax and I'm wondering how best to go about it.
Maybe there is something wrong with my system by I'm not being able to use 0.2.0 or 0.3.0-SNAPSHOT.
Current system:
Leiningen 2.7.1 on Java 1.8.0_11 Java HotSpot(TM) 64-Bit Server VM
The first problem I was facing was compiling fn-fx.util.reflect-utils
Trying to def all-javafx-types it complains in the first line that it can't initialize javafx.stage.Screen
in current thread, only in event thread.
To avoid initializing that class I changed
#(Class/forName %)
to
#(Class/forName % false (.getContextClassLoader (Thread/currentThread)))
so it doesn't try to initialize the class now, just loads it.
Now that part works but I get
Error compiling fn_fx/controls.clj at (27:3)
Caused by java.lang.ClassNotFoundException
javafx.util.converter.LocalDateTimeStringConverter
Any ideas of what I'm doing wrong?
Howdy, I am trying to use the ui/file-chooser
macro, but I don't really know what parameters to give it since there is no documentation. Can you provide an example?
How can I add my to my scene? In Java it's done using a method, so I'm not sure how to translate that to fn-fx. Do you have an example?
Right now if you call (doc fn-fx.diff/render)
in a repl, you don't get any result. Many of fn-fx's functions lack usable documentation and it makes it more frustrating to program on the repl.
I understand that many of the items under fn-fx.controls can't easily have documentation, but it would be nice if other, more central functions did.
I'm sure I'm doing something wrong, but I can't figure it out. The sliders I create get into an endless change loop if I make changes too fast. It seems like when the new value is put into the view, that triggers the handler again. How can I avoid this?
Here's what I do:
(defn- my-slider-value-changed-handler [my-app-state event-data]
(swap! my-app-state assoc :my-slider-value (:fn-fx.listen/new event-data)))
(defui MySliderExample
(render [this {:keys [my-slider-value] :as my-app-state}]
[(ui/slider
:value my-slider-value
:listen/value {:event ::slider-value-changed})]))
FWIW, I tried rounding these values to lower the number of swaps on the atom, but that didn't have any effect.
seems like a problem with clojars package?
my project.clj:
(defproject func "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.8.0"]
[fn-fx "0.1.0-SNAPSHOT"]]
:main func.core)
my core.clj:
(ns func.core
(:require [fn-fx.fx-dom :as dom]
[fn-fx.diff :refer [component defui render should-update?]]
[fn-fx.render :refer [ui]]))
(defn -main []
(let [u (ui :stage
:title "Hello World!"
:shown true
:scene (ui :scene
:width 300
:height 250
:root (ui :stack-pane
:children [(ui :button
:text "Say 'Hello World'"
:on-action {:say "Hello World!"})])))
handler-fn (fn [evt]
(println "Received Event: " evt))]
(dom/app u handler-fn)))
the error message:
java.io.FileNotFoundException: Could not locate fn_fx/fx_dom__init.class or fn_fx/fx_dom.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure file name., compiling:(core.clj:1:1)
Openjfx is a months out and there are some significant changes:
are there plans for supporting openjfx?
Been getting some errors when compiling my code with a singularly unhelpful stacktrace:
#error {
:cause nil
:via
[{:type java.lang.NullPointerException
:message nil
:at [fn_fx.render_core$get_getter invokeStatic render_core.clj 320]}]
:trace
[[fn_fx.render_core$get_getter invokeStatic render_core.clj 320]
[fn_fx.render_core$get_getter invoke render_core.clj 313]
[fn_fx.render_core$get_property invokeStatic render_core.clj 104]
[fn_fx.render_core$get_property invoke render_core.clj 103]
[fn_fx.fx_dom.FXDom$fn__18478 invoke fx_dom.clj 32]
[clojure.lang.AFn run AFn.java 22]
[com.sun.javafx.application.PlatformImpl lambda$null$173 PlatformImpl.java 295]
[java.security.AccessController doPrivileged AccessController.java -2]
[com.sun.javafx.application.PlatformImpl lambda$runLater$174 PlatformImpl.java 294]
[com.sun.glass.ui.InvokeLaterDispatcher$Future run InvokeLaterDispatcher.java 95]
[com.sun.glass.ui.gtk.GtkApplication _runLoop GtkApplication.java -2]
[com.sun.glass.ui.gtk.GtkApplication lambda$null$49 GtkApplication.java 139]
[java.lang.Thread run Thread.java 745
]]}
The errors are most likely my fault, but a better error message (so I could find out what my mistake was), would be great.
See this problem on Windows 10 x64
As a prelude to addressing issues #21, #26, #27, and #28, it would be great to autogenerate API docs from the master branch, and publish them on GitHub pages.
Even though those API docs will likely be *cough* "rough" to begin with, by airing our dirty laundry we create pressure on ourselves to fix the docstrings in the codebase.
As per TravisCI's instructions, the sudo:false
setting in the TravisCI configuration needs to be removed.
-main
Expect "MainPane content!" to change to "Settings content!"
"MainPane content!" stays displayed
Windows 10 x64, JDK 1.8.0_191 (also does not work under OpenJDK 11.0.1 with the other dependency)
Happened in a more complex program of mine. I can get the change to work by wrapping one of the GridPane
s with a StackPane
, apparently that manages to "trick" the diff
algorithm into thinking something actually changed.
You can see that in the example repository in the workaround branch.
I managed to trace the bug to somewhere in the diff-component
fn in fn-fx.diff
, but didn't manage to understand that fn.
Using mouse running other-examples.shapes-3d triggers assert:
Can't convert 0 of type class java.lang.Long to int
Having this new function in render-core
fixes the problem:
(defmethod convert-value
[java.lang.Long Integer/TYPE]
[value _]
(int value))
Request implement a release process that publishes to clojars
Example should be running.
Window opens, after that the following stacktrace:
Syntax error compiling at (reflect_utils.clj:36:32).
Couldn't find subtypes of Object. Make sure SubTypesScanner initialized to include Object class - new SubTypesScanner(false)
Oct 30, 2018 8:58:17 PM clojure.tools.logging$eval570$fn__573 invoke
SEVERE: Unhandled REPL handler exception processing message {:op stacktrace, :pprint-fn clojure.pprint/pprint, :print-length 50, :print-level 50, :session 133612c4-ddf3-449d-ba10-65f15bb837d9, :id 13}
java.lang.NullPointerException
at clojure.string$replace_first.invokeStatic(string.clj:165)
at clojure.string$replace_first.invoke(string.clj:138)
at cider.nrepl.middleware.stacktrace$relative_path.invokeStatic(stacktrace.clj:204)
at cider.nrepl.middleware.stacktrace$relative_path.invoke(stacktrace.clj:198)
at cider.nrepl.middleware.stacktrace$extract_location.invokeStatic(stacktrace.clj:219)
at cider.nrepl.middleware.stacktrace$extract_location.invoke(stacktrace.clj:206)
at clojure.core$comp$fn__5707.invoke(core.clj:2561)
at clojure.core$map$fn__5766.invoke(core.clj:2747)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:51)
at clojure.lang.RT.seq(RT.java:529)
at clojure.core$seq__5302.invokeStatic(core.clj:137)
at clojure.core$seq__5302.invoke(core.clj:137)
at cider.nrepl.middleware.stacktrace$handle_stacktrace.invokeStatic(stacktrace.clj:312)
at cider.nrepl.middleware.stacktrace$handle_stacktrace.invoke(stacktrace.clj:309)
at clojure.lang.Var.invoke(Var.java:388)
at cider.nrepl$wrap_stacktrace$fn__6591.invoke(nrepl.clj:436)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_undef$fn__6623.invoke(nrepl.clj:495)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at refactor_nrepl.middleware$wrap_refactor$fn__6169.invoke(middleware.clj:214)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_classpath$fn__6475.invoke(nrepl.clj:166)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_apropos$fn__6467.invoke(nrepl.clj:158)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_complete$fn__6483.invoke(nrepl.clj:172)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_version$fn__6631.invoke(nrepl.clj:503)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_slurp$fn__6459.invoke(nrepl.clj:150)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_trace$fn__6607.invoke(nrepl.clj:466)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_ns$fn__6543.invoke(nrepl.clj:308)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_info$fn__6517.invoke(nrepl.clj:236)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_profile$fn__6559.invoke(nrepl.clj:345)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_resource$fn__6575.invoke(nrepl.clj:408)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_spec$fn__6583.invoke(nrepl.clj:420)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__1160.invoke(interruptible_eval.clj:247)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_inspect$fn__6527.invoke(nrepl.clj:255)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_debug$fn__6493.invoke(nrepl.clj:192)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_enlighten$fn__6501.invoke(nrepl.clj:218)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at clojure.tools.nrepl.middleware.session$add_stdin$fn__1243.invoke(session.clj:238)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at clojure.tools.nrepl.middleware.load_file$wrap_load_file$fn__1286.invoke(load_file.clj:79)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_content_type$fn__6451.invoke(nrepl.clj:139)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_pprint$fn__6441.invoke(nrepl.clj:119)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_refresh$fn__6567.invoke(nrepl.clj:382)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_tracker$fn__6615.invoke(nrepl.clj:484)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at clojure.tools.nrepl.middleware.pr_values$pr_values$fn__1076.invoke(pr_values.clj:22)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_test$fn__6599.invoke(nrepl.clj:446)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl.middleware.pprint$handle_pprint_fn.invokeStatic(pprint.clj:61)
at cider.nrepl.middleware.pprint$handle_pprint_fn.invoke(pprint.clj:56)
at clojure.lang.Var.invoke(Var.java:388)
at cider.nrepl$wrap_pprint_fn$fn__6431.invoke(nrepl.clj:100)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at cider.nrepl$wrap_out$fn__6551.invoke(nrepl.clj:336)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at clojure.tools.nrepl.middleware.session$session$fn__1228.invoke(session.clj:192)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__877.invoke(middleware.clj:22)
at clojure.tools.nrepl.server$handle_STAR_.invokeStatic(server.clj:19)
at clojure.tools.nrepl.server$handle_STAR_.invoke(server.clj:16)
at clojure.tools.nrepl.server$handle$fn__1301.invoke(server.clj:28)
at clojure.core$binding_conveyor_fn$fn__5654.invoke(core.clj:2022)
at clojure.lang.AFn.call(AFn.java:18)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:844)
Howdy, I was trying to use the ui/combo-box
macro, and I had a hell of a time since there was no documentation. I was able to figure out how to add list items by adding the :items ["my item"]
thing, but I believe that that is something that should be documented, or at the very least, given an example.
I would be happy to help contribute to documentation if it would be useful.
On Ubuntu Cuttlefish (18.10)
Install leiningen
from the repository
Install openjdk-8-jre
from the repository
Try to run a fn-fx project and it will not find JavaFX
Installing leiningen
installs openjdk-8-jre-headless
. But after installing openjdk-8-jre
it should include JavaFX as I understand it.
What I get instead is a crash:
Exception in thread "main" java.lang.NoClassDefFoundError: javafx/scene/Group, compiling:(asparapiss/svg2jfx.clj:16:3)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6875)
at clojure.lang.Compiler.analyze(Compiler.java:6669)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6856)
at clojure.lang.Compiler.analyze(Compiler.java:6669)
at clojure.lang.Compiler.analyze(Compiler.java:6625)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:6001)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5380)
[etc]
I've also tried to install the openjfx
package (which I think is for Java 11) as well as the openjdk-8-jdk
So I'm not sure if this is a bug or I'm missing something obvious here (like some additional package). I've had this project running before on a Debian system (using version 0.4.0), but unfortunately I don't remember how I set up then (but I remember it not being straightforward). I've lost that setup and had to switch to an Ubuntu system. When trying to get this old project running I ran into this crash. My project.clj
has a
[fn-fx/fn-fx-javafx "0.5.0-SNAPSHOT"]
I tried the old halgari 0.4.0 as well and have the same issue
And my namespace starts with a
If you point me to another fn-fx
project to test I can do that as well
I wonder if it is possible to use HTML as frontend?
lein do version, test
)Tests run, and pass (taking note of issue #45).
$ lein do version, test
(Warning: profile :openjfx1.8 not found.)
Leiningen 2.8.1 on Java 1.8.0_192 OpenJDK 64-Bit Server VM
(Warning: profile :openjfx1.8 not found.)
Exception in thread "main" java.lang.ClassNotFoundException: javafx.application.Platform, compiling:(fn_fx/util.clj:1:1)
at clojure.lang.Compiler.load(Compiler.java:7526)
at clojure.lang.RT.loadResourceScript(RT.java:379)
at clojure.lang.RT.loadResourceScript(RT.java:370)
at clojure.lang.RT.load(RT.java:460)
at clojure.lang.RT.load(RT.java:426)
at clojure.core$load$fn__6548.invoke(core.clj:6046)
at clojure.core$load.invokeStatic(core.clj:6045)
at clojure.core$load.doInvoke(core.clj:6029)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5848)
at clojure.core$load_one.invoke(core.clj:5843)
at clojure.core$load_lib$fn__6493.invoke(core.clj:5888)
at clojure.core$load_lib.invokeStatic(core.clj:5887)
at clojure.core$load_lib.doInvoke(core.clj:5868)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$load_libs.invokeStatic(core.clj:5925)
at clojure.core$load_libs.doInvoke(core.clj:5909)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$require.invokeStatic(core.clj:5947)
at clojure.core$require.doInvoke(core.clj:5947)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at fn_fx.diff$eval367$loading__6434__auto____368.invoke(diff.clj:1)
at fn_fx.diff$eval367.invokeStatic(diff.clj:1)
at fn_fx.diff$eval367.invoke(diff.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:7062)
at clojure.lang.Compiler.eval(Compiler.java:7051)
at clojure.lang.Compiler.load(Compiler.java:7514)
at clojure.lang.RT.loadResourceScript(RT.java:379)
at clojure.lang.RT.loadResourceScript(RT.java:370)
at clojure.lang.RT.load(RT.java:460)
at clojure.lang.RT.load(RT.java:426)
at clojure.core$load$fn__6548.invoke(core.clj:6046)
at clojure.core$load.invokeStatic(core.clj:6045)
at clojure.core$load.doInvoke(core.clj:6029)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5848)
at clojure.core$load_one.invoke(core.clj:5843)
at clojure.core$load_lib$fn__6493.invoke(core.clj:5888)
at clojure.core$load_lib.invokeStatic(core.clj:5887)
at clojure.core$load_lib.doInvoke(core.clj:5868)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$load_libs.invokeStatic(core.clj:5925)
at clojure.core$load_libs.doInvoke(core.clj:5909)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$require.invokeStatic(core.clj:5947)
at clojure.core$require.doInvoke(core.clj:5947)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at fn_fx.diff_test$eval361$loading__6434__auto____362.invoke(diff_test.clj:1)
at fn_fx.diff_test$eval361.invokeStatic(diff_test.clj:1)
at fn_fx.diff_test$eval361.invoke(diff_test.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:7062)
at clojure.lang.Compiler.eval(Compiler.java:7051)
at clojure.lang.Compiler.load(Compiler.java:7514)
at clojure.lang.RT.loadResourceScript(RT.java:379)
at clojure.lang.RT.loadResourceScript(RT.java:370)
at clojure.lang.RT.load(RT.java:460)
at clojure.lang.RT.load(RT.java:426)
at clojure.core$load$fn__6548.invoke(core.clj:6046)
at clojure.core$load.invokeStatic(core.clj:6045)
at clojure.core$load.doInvoke(core.clj:6029)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5848)
at clojure.core$load_one.invoke(core.clj:5843)
at clojure.core$load_lib$fn__6493.invoke(core.clj:5888)
at clojure.core$load_lib.invokeStatic(core.clj:5887)
at clojure.core$load_lib.doInvoke(core.clj:5868)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$load_libs.invokeStatic(core.clj:5925)
at clojure.core$load_libs.doInvoke(core.clj:5909)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$require.invokeStatic(core.clj:5947)
at clojure.core$require.doInvoke(core.clj:5947)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$apply.invoke(core.clj:652)
at user$eval233.invokeStatic(form-init3481129458187765184.clj:1)
at user$eval233.invoke(form-init3481129458187765184.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:7062)
at clojure.lang.Compiler.eval(Compiler.java:7052)
at clojure.lang.Compiler.load(Compiler.java:7514)
at clojure.lang.Compiler.loadFile(Compiler.java:7452)
at clojure.main$load_script.invokeStatic(main.clj:278)
at clojure.main$init_opt.invokeStatic(main.clj:280)
at clojure.main$init_opt.invoke(main.clj:280)
at clojure.main$initialize.invokeStatic(main.clj:311)
at clojure.main$null_opt.invokeStatic(main.clj:345)
at clojure.main$null_opt.invoke(main.clj:342)
at clojure.main$main.invokeStatic(main.clj:424)
at clojure.main$main.doInvoke(main.clj:387)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:702)
at clojure.main.main(main.java:37)
Caused by: java.lang.ClassNotFoundException: javafx.application.Platform
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at clojure.lang.DynamicClassLoader.findClass(DynamicClassLoader.java:69)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at clojure.lang.DynamicClassLoader.loadClass(DynamicClassLoader.java:77)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at clojure.lang.RT.classForName(RT.java:2204)
at clojure.lang.RT.classForNameNonLoading(RT.java:2217)
at fn_fx.util$eval427$loading__6434__auto____428.invoke(util.clj:1)
at fn_fx.util$eval427.invokeStatic(util.clj:1)
at fn_fx.util$eval427.invoke(util.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:7062)
at clojure.lang.Compiler.eval(Compiler.java:7051)
at clojure.lang.Compiler.load(Compiler.java:7514)
... 97 more
Tests failed.
When running the tests locally on JDK 8 (i.e. with bundled JavaFX), I periodically see the following error, and a similar error has shown up on TravisCI too.
I don't seem to have the same issue on JDK 11 / OpenJFX 11, though it has occurred on TravisCI with that version combo.
I haven't discovered a pattern to its occurrence - often just rerunning the tests will succeed (both locally and on TravisCI). This is especially puzzling on TravisCI, since the container the tests run in there is thrown away between every single test run, significantly reducing the possibility that some kind of state is being preserved between successive runs of the tests.
$ lein do clean, version, test, jar
Leiningen 2.8.1 on Java 1.8.0_192 Java HotSpot(TM) 64-Bit Server VM
lein test fn-fx.diff-test
lein test fn-fx.fx-dom-test
lein test :only fn-fx.fx-dom-test/static-member-tests
ERROR in (static-member-tests) (fx_dom_test.clj:10)
Uncaught exception, not in assertion.
expected: nil
actual: java.lang.AssertionError: Assert failed: comp
at fn_fx.fx_dom_test$get_prop.invokeStatic (fx_dom_test.clj:10)
fn_fx.fx_dom_test$get_prop.invoke (fx_dom_test.clj:10)
fn_fx.fx_dom_test$fn__4061.invokeStatic (fx_dom_test.clj:116)
fn_fx.fx_dom_test/fn (fx_dom_test.clj:99)
clojure.test$test_var$fn__9209.invoke (test.clj:716)
clojure.test$test_var.invokeStatic (test.clj:716)
clojure.test$test_var.invoke (test.clj:707)
clojure.test$test_vars$fn__9235$fn__9240.invoke (test.clj:734)
clojure.test$default_fixture.invokeStatic (test.clj:686)
clojure.test$default_fixture.invoke (test.clj:682)
clojure.test$test_vars$fn__9235.invoke (test.clj:734)
clojure.test$default_fixture.invokeStatic (test.clj:686)
clojure.test$default_fixture.invoke (test.clj:682)
clojure.test$test_vars.invokeStatic (test.clj:730)
clojure.test$test_all_vars.invokeStatic (test.clj:736)
clojure.test$test_ns.invokeStatic (test.clj:757)
clojure.test$test_ns.invoke (test.clj:742)
user$eval233$fn__294.invoke (form-init3321944168700773224.clj:1)
clojure.lang.AFn.applyToHelper (AFn.java:156)
clojure.lang.AFn.applyTo (AFn.java:144)
clojure.core$apply.invokeStatic (core.clj:659)
clojure.core$apply.invoke (core.clj:652)
leiningen.core.injected$compose_hooks$fn__163.doInvoke (form-init3321944168700773224.clj:1)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:657)
clojure.core$apply.invoke (core.clj:652)
leiningen.core.injected$run_hooks.invokeStatic (form-init3321944168700773224.clj:1)
leiningen.core.injected$run_hooks.invoke (form-init3321944168700773224.clj:1)
leiningen.core.injected$prepare_for_hooks$fn__168$fn__169.doInvoke (form-init3321944168700773224.clj:1)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.lang.AFunction$1.doInvoke (AFunction.java:29)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$map$fn__5587.invoke (core.clj:2747)
clojure.lang.LazySeq.sval (LazySeq.java:40)
clojure.lang.LazySeq.seq (LazySeq.java:49)
clojure.lang.Cons.next (Cons.java:39)
clojure.lang.RT.boundedLength (RT.java:1785)
clojure.lang.RestFn.applyTo (RestFn.java:130)
clojure.core$apply.invokeStatic (core.clj:659)
clojure.test$run_tests.invokeStatic (test.clj:767)
clojure.test$run_tests.doInvoke (test.clj:767)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:657)
clojure.core$apply.invoke (core.clj:652)
user$eval233$fn__306$fn__339.invoke (form-init3321944168700773224.clj:1)
user$eval233$fn__306$fn__307.invoke (form-init3321944168700773224.clj:1)
user$eval233$fn__306.invoke (form-init3321944168700773224.clj:1)
user$eval233.invokeStatic (form-init3321944168700773224.clj:1)
user$eval233.invoke (form-init3321944168700773224.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7062)
clojure.lang.Compiler.eval (Compiler.java:7052)
clojure.lang.Compiler.load (Compiler.java:7514)
clojure.lang.Compiler.loadFile (Compiler.java:7452)
clojure.main$load_script.invokeStatic (main.clj:278)
clojure.main$init_opt.invokeStatic (main.clj:280)
clojure.main$init_opt.invoke (main.clj:280)
clojure.main$initialize.invokeStatic (main.clj:311)
clojure.main$null_opt.invokeStatic (main.clj:345)
clojure.main$null_opt.invoke (main.clj:342)
clojure.main$main.invokeStatic (main.clj:424)
clojure.main$main.doInvoke (main.clj:387)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.lang.Var.applyTo (Var.java:702)
clojure.main.main (main.java:37)
lein test :only fn-fx.fx-dom-test/test-basic-component-properties
FAIL in (test-basic-component-properties) (fx_dom_test.clj:23)
expected: (= (get-prop (clojure.core/deref root) :title) "Hello")
actual: (not (= nil "Hello"))
Ran 9 tests containing 59 assertions.
1 failures, 1 errors.
Tests failed.
Can you show two more examples of fn-fx in your video?
One would be the settings to run it as a Java Application in Cursive.
The other would be the settings to run it as a Clojure Application in Cursive.
I've been able to run the examples via the REPL but have had issues trying to get them to run those two ways above. Doc updates with screenshots of the settings would be greatly appreciated if you have the time.
Thanks for the cool library.
The last commits are from year ago..
Although it's possible to load FXML files into an fn-fx
app, doing so requires Java interop. It would be nicer if this were supported directly and idiomatically by fn-fx
.
Currently the examples are run in 2 different ways. It would be great to standardise on a single approach, to make it easier for newcomers to the library.
(require '[getting-started.01-hello-word])
(note: (-main)
is automatically invoked)(require '[getting-started.02-form :as form]) (form/-main)
(require '[other-examples.shapes-3d :as shapes-3d]) (shapes-3d/-main)
(require '[other-examples.todo :as todo]) (todo/-main)
(defui Choice
(render [this _]
(ui/choice-box
:on-action {:event :choose-env :this this }
:items ["development"
"staging"
"production"] )))
In the "choose-env" handle, I have no access to what item was chosen. I tried to pass "this" as an argument and call (.getSelectionModel this) in the event handler, but there's no such method. How are you supposed to get the chosen item ?
How can I use a button inside cell?
I tried with Java examples but that thing about extend
is too dificult
Color should have changed ie firebrick.
Text remains black.
master branch, ubuntu 19.04, javafx11
Is it possible to start with a fxml file from SceneBuilder?
http://gluonhq.com/labs/scene-builder/
Example:
https://github.com/andrenventer/clojure-javafx/blob/master/resources/window.fxml
I have a setup where the name of my .css file is stored in the data-state atom. I tried using the method suggested by this blog post on how to dynamically update the style on the repl. However, about 50% of the time when I set the css file to a new string (with (swap! data-state assoc-in [:ui :stylesheets] ["main.css"])
) the below error occurs. Even if the error doesn't occur, the window does not update its style. At the very least, I imagine the error message should be improved.
#error {
:cause Assert failed: TODO: Implement this
(= idx (count lst))
:via
[{:type java.lang.AssertionError
:message Assert failed: TODO: Implement this
(= idx (count lst))
:at [fn_fx.fx_dom.FXDom$fn__18087 invoke fx_dom.clj 33]}]
:trace
[[fn_fx.fx_dom.FXDom$fn__18087 invoke fx_dom.clj 33]
[clojure.lang.AFn run AFn.java 22]
[com.sun.javafx.application.PlatformImpl lambda$null$173 PlatformImpl.java 295]
[java.security.AccessController doPrivileged AccessController.java -2]
[com.sun.javafx.application.PlatformImpl lambda$runLater$174 PlatformImpl.java 294]
[com.sun.glass.ui.InvokeLaterDispatcher$Future run InvokeLaterDispatcher.java 95]
[com.sun.glass.ui.gtk.GtkApplication _runLoop GtkApplication.java -2]
[com.sun.glass.ui.gtk.GtkApplication lambda$null$49 GtkApplication.java 139]
[java.lang.Thread run Thread.java 745]]}
"Elapsed time: 3.601076 msecs"
Possibly a clojure question, but I assume it's possible to use this as a template language in a java application?
http://clojure.org/reference/java_interop
maybe? Pardon my unfamiliarity with closure.
Hey Tim!
Great library. Thanks a million for providing it.
Here's a question for you and the community:
I'm having an issue adding a listener to TabPane.selectionModelProperty.selectedIndexProperty
.
I've never had to go two layers deep in fn-fx before, so I may be missing something fairly obvious.
Here's what I'm attempting to do in Java:
tabPane.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue) {
// do something...
}
});
Here's my dream client code in Clojure with fn-fx:
(ui/tab-pane
:selection-model {:selected-index/listener {:event :tab-changed}}
:tabs tabs))
The error I encountered when writing the above code:
Can't convert {:selected-index/listener {:event :tab-changed}} of type class clojure.lang.PersistentArrayMap to class javafx.scene.control.SingleSelectionModel
^ Seems that my attempt at a nested modification [:selection-model :selected-index/listener] failed.
SingleSelectionModel
I attempted to instantiate a SingleSelectionModel
, but it looks like this violates JavaFX's instantiation policy:
(ui/tab-pane
:selection-model (SingleSelectionModel.)
:tabs tabs))
I suspect that there may be something simple for doing a nested modify.
Is there a good workaround or perhaps an insight that I am missing? Many thanks!
@halgari I've deleted the fork (fn-fx/fn-fx-openjfx
) that was preventing the transfer of this repo to the fn-fx
org - the transfer should be possible now.
Apologies for raising a new issue for this, but as part of deleting that fork I also deleted the issue where we had previously been discussing this. 😊
I'm trying to figure out how to make this work with an uberjar. See the reddit thread for some background:
https://www.reddit.com/r/Clojure/comments/370zmg/using_clojure_with_javafx_and_making_an_uberjar/
All the clojure javafx libraries are hobbled by this to some degree which has made distributing a simple clojure javafx app a real chore.
Hello there, first of all, thank you for this wonderful library.
I've been using it instead of regular javafx for the fast few while and I really enjoy using it. However I have encountered a few roadblocks.
What would be the correct way to emulate the infamous "fit-to-parent" AnchorPane functionality? My so far unsuccessful approach was something like this:
(controls/anchor-pane
:children
[(controls/some-control
:anchor-pane/top-anchor 0.0
:anchor-pane/bottom-anchor 0.0
:anchor-pane/left-anchor 0.0
:anchor-pane/right-anchor 0.0)])
But for some controls (ImageView cough) I know, this just won't cut it in the long run. So are there major hurdles for the nested-properties branch to get merged? I looked at the source and am looking forward to the :bind/property syntax with [:id :prop] values. I don't really get the complete picture of what is depending on what right now, but with some pointers I would like to look into this and help if possible/necessary.
As far as I know, currently there is no idiomatic way to define :cell-value-property
for table-column
components. You have to jump through hoops to create an object which implement the java Callback
interface. Currently I am using a custom function, thanks to this blogpost. Here's the code I am using:
(defn cell-value-factory [f]
(reify javafx.util.Callback
(call [this entity]
(javafx.beans.property.ReadOnlyObjectWrapper. (f (.getValue entity))))))
(defui MyTable
(render [this _]
(ui/table-view
:items [{:name "foo" :age 10}
{:name "bar" :age 56}]
:columns [(ui/table-column
:text "Name"
:cell-value-factory (cell-value-factory #(:name %)))
(ui/table-column
:text "Age"
:cell-value-factory (cell-value-factory #(:age %)))])))
While this works; ideally (IMO), the object creation should be handled by the table-column
component itself and :cell-value-factory
should accept plain clojure functions. Like this:
(defui MyTable
(render [this _]
(ui/table-view
:items [{:name "foo" :age 10}
{:name "bar" :age 56}]
:columns [(ui/table-column
:text "Name"
:cell-value-factory #(:name %))
(ui/table-column
:text "Age"
:cell-value-factory #(:age %))])))
The special handling of the :shown property:
fn-fx/src/fn_fx/render_core.clj
Line 386 in a84a1f8
on a Window/Stage immediately causes the show method to be called, potentially before any on-showing/on-shown event handler properties have been set on the component. In my opinion, there should be some sort of lifecycle callback done when the FX component has been fully instantiated where doing things like call show() should be done. I'm still trying to grok this codebase, so I'm not clear where this callback would be inserted.
The Eclipse Foundation now recommends all users of the Eclipse Public License v1.0 upgrade to Eclipse Public License v2.0 (see this FAQ item).
Exception in thread "JavaFX Application Thread"
java.lang.ClassCastException: javafx.stage.Stage cannot be cast to javafx.scene.Node
at fn_fx.fx_tree_search$find_child_by_id.invokeStatic(fx_tree_search.clj:23)
at fn_fx.fx_tree_search$find_child_by_id.invoke(fx_tree_search.clj:22)
at fn_fx.fx_tree_search$find_nearest_by_id.invokeStatic(fx_tree_search.clj:37)
at fn_fx.fx_tree_search$find_nearest_by_id.invoke(fx_tree_search.clj:34)
at fn_fx.render_core$gather_event_data$fn__18684.invoke(render_core.clj:279)
at clojure.lang.PersistentArrayMap.kvreduce(PersistentArrayMap.java:373)
at clojure.core$fn__9354.invokeStatic(core.clj:6721)
at clojure.core$fn__9354.invoke(core.clj:6706)
at clojure.core.protocols$fn__9145$G__9140__9154.invoke(protocols.clj:174)
at clojure.core$reduce_kv.invokeStatic(core.clj:6732)
at clojure.core$reduce_kv.invoke(core.clj:6723)
at fn_fx.render_core$gather_event_data.invokeStatic(render_core.clj:275)
at fn_fx.render_core$gather_event_data.invoke(render_core.clj:269)
at fn_fx.render_core$get_add_listener$fn$reify__18691.changed(render_core.clj:300)
Would it be possible to have an example of calling a method on a ui object? As an example this does not work:
(def transition (ui/parallel-transition a-rect a-translate))
(.play transition)
The example in the README is not working anymore (e.g. ui
is not in fn-fx.render
anymore).
I suggest to either just refer to the examples folder or replace it with a simple working example in the README itself.
get jar files
java.lang.ClassNotFoundException: javafx.application.Platform, compiling:(util.clj:1:1)
Exception in thread "main" java.lang.ClassNotFoundException: javafx.application.Platform, compiling:(util.clj:1:1)
Leiningen 2.9.1 on Java 11 Java HotSpot(TM) 64-Bit Server VM
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.