Quelle est la meilleure façon de faire des GUI dans Clojure ?
Existe-t-il un exemple d'un wrapper fonctionnel Swing ou SWT ? Ou une certaine intégration avec JavaFX description déclarative de l'interface graphique qui pourrait être facilement enveloppée dans s-expressions en utilisant de la macrologie?
Des tutoriels?
Je suggérerai humblement Balançoire .
Voici un tutoriel basé sur REPL qui suppose non Java ou connaissance Swing.
La balançoire ressemble beaucoup à ce que suggère @tomjen. Voici "Bonjour tout le monde":
(use 'seesaw.core)
(-> (frame :title "Hello"
:content "Hello, Seesaw"
:on-close :exit)
pack!
show!)
et voici l'exemple de @Abhijith et @ dsm, traduit assez littéralement:
(ns seesaw-test.core
(:use seesaw.core))
(defn handler
[event]
(alert event
(str "<html>Hello from <b>Clojure</b>. Button "
(.getActionCommand event) " clicked.")))
(-> (frame :title "Hello Swing" :on-close :exit
:content (button :text "Click Me" :listen [:action handler]))
pack!
show!)
Stuart Sierra a récemment publié une série d'articles de blog sur le développement d'interface graphique avec clojure (et swing). Commencez ici: http://stuartsierra.com/2010/01/02/first-steps-with-clojure-swing
Si vous voulez faire de la programmation GUI, je pointerais vers Convertisseur de température ou la colonie de fourmis .
Beaucoup de choses dans Swing se font par sous-classification, en particulier si vous créez des composants personnalisés. Pour cela, il existe deux fonctions/macros essentielles: proxy et gen-class .
Maintenant, je comprends où vous allez avec la manière plus Lispy. Je ne pense pas qu'il y ait encore quelque chose comme ça. Je déconseille fortement d'essayer de construire un cadre de construction GUI grandiose à la CLIM , mais pour faire quelque chose de plus Lispy: commencez à écrire votre application Swing et votre résumé sur vos modèles communs avec des macros. En faisant cela, vous pouvez vous retrouver avec une langue pour écrire votre type d'interface graphique, ou peut-être des trucs très génériques qui peuvent être partagés et croître.
Une chose que vous perdez lors de l'écriture des GUI dans Clojure est l'utilisation d'outils comme Matisse. Cela peut être un point fort pour écrire certaines parties dans Java (l'interface graphique) et certaines parties dans Clojure (la logique). Ce qui a du sens, car dans la logique, vous pourrez construire un langage pour votre type de logique utilisant des macros et je pense qu'il y a plus à y gagner qu'avec l'interface graphique. Evidemment, cela dépend de votre application.
De cela page :
(import '(javax.swing JFrame JButton JOptionPane)) ;'
(import '(Java.awt.event ActionListener)) ;'
(let [frame (JFrame. "Hello Swing")
button (JButton. "Click Me")]
(.addActionListener button
(proxy [ActionListener] []
(actionPerformed [evt]
(JOptionPane/showMessageDialog nil,
(str "<html>Hello from <b>Clojure</b>. Button "
(.getActionCommand evt) " clicked.")))))
(.. frame getContentPane (add button))
(doto frame
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
.pack
(.setVisible true)))
print("code sample");
Et, bien sûr, cela vaut la peine de regarder la section interopérabilité du site Web de clojure.
Personne ne l'a encore suggéré, donc je vais: Navigateur comme plate-forme d'interface utilisateur. Vous pouvez écrire votre application dans Clojure, y compris un serveur HTTP, puis développer l'interface utilisateur en utilisant n'importe quoi de HTML à hiccup , ClojureScript et l'un des milliards de bibliothèques JS dont vous avez besoin. Si vous vouliez un comportement de navigateur cohérent et "look'n'feel d'application de bureau", vous pourriez bundle chrome avec votre application .
Cela semble être la façon dont Light Table est distribué.
Il existe un wrapper pour MigLayout dans clojure contrib. Vous pouvez également jeter un œil à ce Gist . Je mets essentiellement le code que j'écris pendant que j'apprends le swing/miglayout.
l'exemple de dsm réécrit de manière lispy en utilisant contrib.swing-utils
(ns test
(:import (javax.swing JButton JFrame))
(:use (clojure.contrib
[swing-utils :only (add-action-listener)])))
(defn handler
[event]
(JOptionPane/showMessageDialog nil,
(str "<html>Hello from <b>Clojure</b>. Button "
(.getActionCommand event) " clicked.")))
(let [ frame (JFrame. "Hello Swing")
button (JButton. "Click Me") ]
(add-action-listener button handler)
(doto frame
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(.add button)
(.pack)
(.setVisible true)))
Il y a eu parler sur la liste de diffusion à propos de quelques implémentations de Cells (à la Kenny Tilton's Cells ). C'est une façon assez soignée de faire de la programmation GUI.
Je préfère opter pour clojurefx, c'est un peu prématuré, mais cela fonctionne et vous fait gagner du temps.
J'ai commencé mon interface graphique avec une balançoire, puis j'ai essayé un autre composant dans clojurefx.
J'ai fini les deux, et je suis convaincu que je vais refactoriser la balançoire à clojurefx.
Après tout, JavaFX est la voie à suivre.
Il semble plus léger que la balançoire. Ou du moins, l'écrire ..
Les liaisons fonctionnent, les écouteurs fonctionnent, la plupart des composants fonctionnent, sinon, utilisez simplement l'une des macros pour créer un constructeur pour ce cas particulier et le travail effectué. Ou, si vous trouvez cela difficile, écrivez quelques méthodes dans Java et demandez de l'aide pour améliorer clojurefx.
Le gars qui a écrit clojurefx est occupé en ce moment, mais vous pouvez bifurquer le projet et faire quelques corrections.
Voici un autre exemple d'habillage swing très basique:
; time for some swing
(import '(javax.swing JFrame JTable JScrollPane))
(import '(javax.swing.table DefaultTableModel))
(let
[frame (JFrame. "Hello Swing")
dm (DefaultTableModel.)
table (JTable. dm)
scroll (JScrollPane. table)]
(doto dm
(.setNumRows 30)
(.setColumnCount 5))
(.. frame getContentPane (add scroll))
(doto frame
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(.pack)
(.setVisible true)))
J'ai développé une applet Java dans laquelle tout est écrit en Clojure sauf le code applet, qui est écrit en Java. L'applet appelle les rappels init du code Clojure, Paint, etc. depuis Java crochets pour les méthodes définies par le modèle d'applet. Ainsi, le code finit par être 99,999 pour cent de Clojure et vous n'avez pas à penser à la petite pièce Java du tout pour la plupart).
Il y a quelques inconvénients à cette approche, que j'espère discuter plus en détail sur le groupe Google Clojure. Je pense que les développeurs de Clojure devraient inclure une manière native de créer des applications. Actuellement, vous pouvez faire tout ce que vous voulez de l'interface graphique à partir du REPL, mais si vous voulez une application GUI livrable, il est nécessaire d'écrire quelques Java pour appeler le code Clojure. En outre, il semble que le l'architecture d'un Java Applet vous oblige à sortir des meilleures pratiques les plus idiomatiques de Clojure, vous obligeant à utiliser un état mutable, etc.
Mais aussi, je ne suis pas encore très loin avec Clojure et il se peut que ce soit possible et je n'ai pas encore découvert comment le faire correctement.
Je n'ai donc pas vu Fn-Fx sur cette liste, de Timothy Baldridge (halgiri). Il s'agit d'une bibliothèque Clojure fournissant une abstraction fonctionnelle sur JavaFX.
Il peut être trouvé sur Github à https://github.com/halgari/fn-fx .
Pour l'utiliser, assurez-vous que vous utilisez une version récente de Java (1.8 90+) et ajoutez une dépendance au référentiel github en ajoutant ce qui suit à votre project.clj:
:plugins [[lein-git-deps "0.0.1-SNAPSHOT"]]
:git-dependencies [["https://github.com/halgari/fn-fx.git"]]
Je l'ai essayé, et cela fonctionne hors de la boîte.
Clojure et SWT est la meilleure approche pour faire GUI (s). Essentiellement, SWT est une approche de style plug and play pour le développement de logiciels.
Je ne pense pas qu'il y en ait un officiel, mais personnellement, je profiterais du fait que j'utilise l'un des langages les plus puissants au monde et j'imagine juste à quoi ressemblerait le code gui parfait:
(form {:title :on-close dispose :x-size 500 :y-size 450}
[(button {:text "Close" :id 5 :on-click #(System/exit 0) :align :bottom})
(text-field {:text "" :on-change #(.println System/out (:value %)) :align :center})
(combo-box {:text "Chose background colour" :on-change background-update-function
:items valid-colours})])
Votre idée serait différente, mais cela devrait, espérons-le, vous donner une idée.
Mon environnement d'interface utilisateur Clojure préféré utilise IO.js (Node for ES6) + Electron (Container) + Quiescent (ReactJS wrapper) .
Je sais que vous faites allusion à des solutions de bureau classiques, mais le Web correspond assez bien à clojure. J'ai écrit une application audio complète où tout est connecté de sorte que si vous ajoutez de la musique au dossier audio, elle se reflète dans l'interface utilisateur Web. Je dis simplement que l'application Desktop n'est pas le seul moyen :)