Building a non-web GUI app with Clojure


The screenshot is of a Python app that I want to rewrite (actually, rewrite the whole family of apps)in Clojure, but I’ve never even seen code to build non-webapp GUIs in Clojure. As some background, this family of applications all wrap implementations of established algorithms, which can be expected to exceed anything possible in a browser (e.g. specifying more than 1m nodes). What are recommendations on building GUI apps (simple, ugly interfaces like those shown are fine), particularly from the experience of our esteemed Clojureverse community? Direct java interop, leveraging java libraries, or any success stories with Clojure libs?

Related posts:


1 Like

I used cljfx for a thing at work and really liked it. No idea how it would handle crazy many elements though.

Ah! Thanks for the recommend. I’ll definitely check out cljfx

2 Likes

Ya, the ones I know of are Cljfx, Fn-fx, and Seesaw. I think Cljfx is the only one actively maintained. And Seesaw is using swing under the hood, so if Java FX can’t handle all those nodes, you could try with swing (possibly using Seesaw) instead.

There’s also just the Java ones, like SWT which is what Eclipse uses, and AWT, which is the lowest level one, and I think offers the best performance.

When I used cljfx it was super quick, and pleasant, to get help from @vlaaad, when I wondered about something. (In the #cljfx channel at the Clojurians Slack.)

Author of cljfx here. Cljfx is great for reactive forms. I would say JavaFX in itself is not blazingly performant, so it will hiccup on large amount of nodes, but it also has some solid virtualized views: lists and tables that can handle millions of items, while rendering only parts that are visible on screen. If you want something else, like millions of dots on a 2D-grid, you’ll probably need to bring your own culling and spatial hashing to render them efficiently.

I saw SandDance by Microsoft a while ago, that’s a library that seem to cover your use case, since it’s designed to render huge amounts of data — in the browser, using GPU.

Thanks for the suggestions! Great work with cljfx. A few minutes ago I finished working through the interactive development example, and am quite pleased. I’ll try it out with a Dijkstra and 1-million nodes and see how it works.

1 Like

One thing that has me a little concerned about cljfx is that I have no prior experience with javafx, so may not know key concepts. I love the documentation and set of examples you have, but I’m having trouble mentally translating something like my screenshot into cljfx stuff. IE, I need to produce random points that are a undirected graph, have the ability to select a start and an end point from them, and draw paths between them. There might be a million of them, but it’s a one-time drawing fee without any special animation or interactivity needs. How should I get started on something like this graphing project, putting points on a canvas and making them clickable, and drawing paths on them?

I’m sure there’s a way with JavaFx, but I know you can use AWT, which has a Canvas where you can draw on, which I think can be used from Swing as well.

Also, I think for that use case, you could also checkout Java2D and Processing. The former I think has a Clojure wrapper called Clojure2d, and the latter has one called Quil.

I’m not sure Clojure wrappers really improve the situations for those. UX prior to React, was a very imperative game. CljFx brings the React model to JavaFX, but we’re talking components and state. You want want drawing on canvas which I feel is still pretty imperative in nature. So you could also just try out using interop directly if you hit any limitations with the wrappers.

1 Like

JavaFx also has a Canvas: https://docs.oracle.com/javafx/2/canvas/jfxpub-canvas.htm

1 Like

This was just posted to Reddit:

2 Likes

Hi there, I’m the original author of that post - it’s still early days, but I think React Native could be a viable way to write a GUI app in Clojure(script).

If an exclusive target of macOS isn’t desirable, there are a few other projects around that target React Native for the desktop:

Though, all these solutions are probably not desirable if you want to target the JVM/depend on JVM libraries.

However, unlike an Electron approach, the ability to interop with the target platforms programming language of choice (eg, Swift/Obj-C) certainly give you a bit more power in what you can do.

3 Likes

If I understand correctly, Catalist is targetting macOS which leaves me (Linux) with Renatal for reat-native stuff (which I’ve done, it’s promising). Not having dug into the performance questions myself, I would expect CS projects (pushing memory limits) to still have issues because of the Javascript runtime constraints, right? Or am I underestimating the JS runtime?

In my days with golang I used the Lorca library for several small Desktop Apps. Direct call of Go functions and more lightweight than Electron: https://github.com/zserge/lorca

I tried cljs + electron for a bit. Very enjoyable environment, though I’m sure clojure jvm would yield better performance.

1 Like

Hi there, and sorry for the late reply.

You’re correct – you’d need to use one of the React Native impls targeting whatever OS you’re using (eg, react-native-desktop for QT).

I think you’re right – for most use cases, performance using the JS runtime is going to be less than ideal.
This is why I am a big fan of the Xi-editor architecture, where there has been a separation into front-end and a back-end modules.

This is a similar architecture to what I have implemented in my own Cljs desktop app, and the pattern lives as a library called reax.

This may not be relevant to you, especially if you want 100% of the application code written in Clojure, but I think the general pattern can be applied to writing Cljs desktop apps in general (whether Electron, QT, windows, android, etc) :slight_smile: