This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-12-02
Channels
- # adventofcode (76)
- # announcements (1)
- # asami (1)
- # babashka (31)
- # beginners (302)
- # calva (3)
- # cider (1)
- # clj-kondo (1)
- # cljdoc (1)
- # cljfx (63)
- # cljsjs (2)
- # clojure (36)
- # clojure-europe (29)
- # clojure-gamedev (2)
- # clojure-nl (5)
- # clojure-sanfrancisco (2)
- # clojure-spec (2)
- # clojure-uk (71)
- # clojurescript (19)
- # conjure (21)
- # core-async (10)
- # core-matrix (1)
- # cryogen (4)
- # cursive (12)
- # datomic (22)
- # emacs (4)
- # events (1)
- # figwheel-main (7)
- # fulcro (9)
- # graalvm (1)
- # jobs (1)
- # kaocha (17)
- # lambdaisland (1)
- # meander (7)
- # mount (2)
- # nrepl (12)
- # off-topic (35)
- # re-frame (15)
- # reagent (17)
- # remote-jobs (1)
- # reveal (41)
- # shadow-cljs (13)
- # spacemacs (2)
- # tools-deps (24)
Hi, I'm trying to get started with cljfx, tried both with lein and cli but I'm unable to load cljfx.api for some reason
(require '[cljfx.api :as fx])
Execution error (FileNotFoundException) at user/eval14091 (REPL:1).
Could not locate cljfx/api__init.class, cljfx/api.clj or cljfx/api.cljc on classpath.
These are the deps I tried with
{:deps
{org.clojure/clojure {:mvn/version "1.10.1"}}
{commons-io/commons-io {:mvn/version "2.8.0"}}
{cljfx {:git/url "" :sha "LATEST"}}
:paths ["src"]}
Using java 11 on arm64
Weirdly enough, I am able to find and load other namespaces when using lein:
(require '[cljfx.fx :as fx])
works just fine
Please advise?with these deps:
:dependencies [[org.clojure/clojure "1.10.1"]
[commons-io/commons-io "2.8.0"]
[cljfx "1.7.10"]]
(require '[cljfx.api :as fx])
Syntax error compiling at (*cider-repl Projects/clj-dedupe-fs:localhost:36281(clj)*:1:21).
namespace 'cljfx.api' not found
yeah#error {
:cause "namespace 'cljfx.api' not found"
:via
[{:type clojure.lang.Compiler$CompilerException
:message "Syntax error compiling at (*cider-repl Projects/clj-dedupe-fs:localhost:36281(clj)*:1:21)."
:data #:clojure.error{:phase :compile-syntax-check, :line 1, :column 21, :source "*cider-repl Projects/clj-dedupe-fs:localhost:36281(clj)*"}
:at [clojure.core$throw_if invokeStatic "core.clj" 5867]}
{:type java.lang.Exception
:message "namespace 'cljfx.api' not found"
:at [clojure.core$apply invokeStatic "core.clj" 667]}]
[[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$load_libs invokeStatic "core.clj" 5985]
[clojure.core$load_libs doInvoke "core.clj" 5969]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$require invokeStatic "core.clj" 6007]
[clojure.core$require doInvoke "core.clj" 6007]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[clj_dedupe_fs.core$eval15884 invokeStatic "form-init3277701471284635884.clj" 1]
[clj_dedupe_fs.core$eval15884 invoke "form-init3277701471284635884.clj" 1]
[clojure.lang.Compiler eval "Compiler.java" 7177]
[clojure.lang.Compiler eval "Compiler.java" 7132]
[clojure.core$eval invokeStatic "core.clj" 3214]
[clojure.core$eval invoke "core.clj" 3210]
[nrepl.middleware.interruptible_eval$evaluate$fn__2542$fn__2543 invoke "interruptible_eval.clj" 87]
[clojure.lang.AFn applyToHelper "AFn.java" 152]
[clojure.lang.AFn applyTo "AFn.java" 144]
[clojure.core$apply invokeStatic "core.clj" 665]
[clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1973]
[clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1973]
[clojure.lang.RestFn invoke "RestFn.java" 425]
[nrepl.middleware.interruptible_eval$evaluate$fn__2542 invoke "interruptible_eval.clj" 87]
[clojure.main$repl$read_eval_print__9086$fn__9089 invoke "main.clj" 437]
[clojure.main$repl$read_eval_print__9086 invoke "main.clj" 437]
[clojure.main$repl$fn__9095 invoke "main.clj" 458]
[clojure.main$repl invokeStatic "main.clj" 458]
[clojure.main$repl doInvoke "main.clj" 368]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.core$apply invokeStatic "core.clj" 665]
[clojure.core$apply invoke "core.clj" 660]
[refactor_nrepl.ns.slam.hound.regrow$wrap_clojure_repl$fn__11776 doInvoke "regrow.clj" 20]
[clojure.lang.RestFn invoke "RestFn.java" 1523]
[nrepl.middleware.interruptible_eval$evaluate invokeStatic "interruptible_eval.clj" 84]
[nrepl.middleware.interruptible_eval$evaluate invoke "interruptible_eval.clj" 56]
[nrepl.middleware.interruptible_eval$interruptible_eval$fn__2573$fn__2577 invoke "interruptible_eval.clj" 152]
[clojure.lang.AFn run "AFn.java" 22]
[nrepl.middleware.session$session_exec$main_loop__2640$fn__2644 invoke "session.clj" 202]
[nrepl.middleware.session$session_exec$main_loop__2640 invoke "session.clj" 201]
[clojure.lang.AFn run "AFn.java" 22]
[java.lang.Thread run "Thread.java" 834]]}
(ns clj-dedupe-fs.core
(:require
[cljfx.api :as fx])
(:import
[javafx.stage FileChooser]
[javafx.event ActionEvent]
[javafx.scene Node]
( File)
( FileUtils)))
If you can require other nses such as cljfx.fx
, it probably means there is some exception during the start of JavaFX runtime
Import succeeded, startup failed with exception
Execution error (IllegalStateException) at com.sun.javafx.application.PlatformImpl/startup (PlatformImpl.java:182).
Toolkit already initialized
Loading library prism_es2 from resource failed: java.lang.UnsatisfiedLinkError: /home/bsless/.openjfx/cache/14/libprism_es2.so: /home/bsless/.openjfx/cache/14/libprism_es2.so: cannot open shared object file: No such file or directory (Possible cause: can't load AMD 64-bit .so on a AARCH64-bit platform)
java.lang.UnsatisfiedLinkError: /home/bsless/.openjfx/cache/14/libprism_es2.so: /home/bsless/.openjfx/cache/14/libprism_es2.so: cannot open shared object file: No such file or directory (Possible cause: can't load AMD 64-bit .so on a AARCH64-bit platform)
I would say yes, there are javafx native libs for various platforms, and I don’t remember seeing arm among them…
Also have a preemptive question: uberjars built with javafx work cross platform on windows, linux and mac or do I need to make sure some extra deps are included or have specific builds?
by default JavaFX pulls native libraries for the same platform the build tool is running on and skips others, so uberjar will work only on the platform the uberjar is built on
if you want to create cross-platform uberjar, you’ll need to specify all classifiers explicitly, e.g. like it’s done here https://github.com/defold/defold/blob/editor-dev/editor/project.clj#L81-L108
if you want to create cross-platform application, I’d recommend looking at https://github.com/cljfx/hn
Thanks again 🙂 I find the documentation a bit obtuse so I have resorted to reading the README very slowly and carefully and working through the examples. Any recommendations on getting started or a development guide? I'm not familiar with JavaFX or UI development at all, and I think what I'm missing the most (maybe?) is discoverability. How do I know tables should have cells? How can I know what attributes are there? That kind of stuff.
I thought about making some sort of a repl helper that answers these questions, but time/priorities…
what I do is:
- use javafx javadoc to see what options are available https://openjfx.io/javadoc/12/javafx.graphics/javafx/scene/Node.html in JavaFX
- open cljfx.fx.*
files to get a reminder of what are props
for example, if I want to configure a table, I open cljfx/fx/table_view.clj
to see its props and https://openjfx.io/javadoc/12/javafx.controls/javafx/scene/control/TableView.html to see its docs
What do you think about qualifying each view's props with a ns? for example a table would map to fx.table/prop-name
?
I thought about it at the start, but decided not to do it because you’ll have to deal with inheritance, e.g. some table props are coming from its superclass, so the use will be something like {:fx/type :fx.type/table :fx.table/items [] :fx.control/tooltip {...} :fx.node/style {...}}
maybe that was a mistake to not do it, what do you think? I didn’t like the idea of having to keep this class hierarchy in the code, but perhaps it’s “essential”?
It looks like in any case I'm forced to know and understand JavaFX and consult its documentation, so perhaps reflecting the class taxonomy might not be too harmful. It would also direct the user to the appropriate class they want to configure when referring to the documentation instead of jumping around.
Another option / complement to this idea is using specs to describe the different views.
Even adding a simple utility function which can be called on the :fx/type
for user convenience will go a very long way, something like (api/props-for :table)
which will give a list of keys or a map of key-type.