Quelle est la meilleure façon de créer des interfaces graphiques dans Clojure?


150

Quelle est la meilleure façon de créer des interfaces graphiques dans Clojure ?

Existe-t-il un exemple de wrapper Swing ou SWT fonctionnel ? Ou une intégration avec la description déclarative de l'interface graphique JavaFX qui pourrait être facilement enveloppée dans des expressions s en utilisant une macrologie?

Des tutoriels?

Réponses:


121

Je suggérerai humblement Seesaw .

Voici un didacticiel basé sur REPL qui ne suppose aucune connaissance de Java ou de Swing.


La balançoire ressemble beaucoup à ce que @tomjen suggère. Voici "Hello, World":

(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!)

2
rendre Swing amusant? Ils ont dit que ce n'était pas possible!
Michael Bylstra

9
Il n'y a pas besoin d'être humble - vous pouvez être très fier de celui-ci! +1!
mydoghasworms

7
-1: Il y a un bug dans votre code. Il dit "Bonjour, balançoire" au lieu de "Bonjour, Monde". </Joke>
Thomas Eding

1
Vraiment? Balançoire? Cela ne limite-t-il pas le développeur aux fonctionnalités offertes par Swing, juste à un niveau d'abstraction plus élevé, le cas échéant? Clojure rend-il les applications moins obsolètes ou améliore-t-il d'une manière ou d'une autre tous les domaines dans lesquels Swing est faible? Je parle des fixations et du MVC et de tous ces "nouveaux" trucs que Swing propose désormais en soi. Est-il en quelque sorte corrigé par les fonctionnalités linguistiques de Clojure?
Zelphir Kaltstahl

1
Il a choisi de faire une abstraction focalisée sur Swing spécifiquement. Rien de mal avec ça ...
Kenogu Labz


16

Si vous voulez faire de la programmation GUI, je pointerais vers le convertisseur de température ou la colonie de fourmis .

Beaucoup de choses dans Swing sont effectuées 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 la plus Lispy. Je ne pense pas qu'il y ait encore quelque chose comme ça. Je déconseillerais fortement d'essayer de créer un cadre grandiose de création d'interface graphique à la CLIM , mais pour faire quelque chose de plus Lispy: commencez à écrire votre application Swing et résumez vos modèles communs avec des macros. En faisant cela, vous pouvez vous retrouver avec un langage pour écrire votre type d'interface graphique, ou peut-être des éléments très génériques qui peuvent être partagés et évolués.

Une chose que vous perdez lors de l'écriture des interfaces graphiques dans Clojure est l'utilisation d'outils comme Matisse. Cela peut être un point fort pour écrire certaines parties en Java (l'interface graphique) et certaines parties en Clojure (la logique). Ce qui est en fait logique, car dans la logique, vous serez en mesure de créer un langage pour votre type de logique en utilisant des macros et je pense qu'il y a plus à gagner qu'avec l'interface graphique. Évidemment, cela dépend de votre application.


2
Ne vous inquiétez pas de perdre Mattisse. Vous pouvez utiliser miglayout.com , qui est suffisamment puissant pour que vous puissiez faire les mises en page à la main.
tomjen

Vous pouvez utiliser Matisse avec Clojure, car le code généré n'est que du code Java auquel Clojure peut accéder de manière transparente. Il y a en fait un tutoriel pour ça quelque part ...
Rayne

3
Je me demande quand nous obtenons le premier concepteur d'interface graphique à sortie clojure. En raison de l'homoiconicité, le code généré ne devrait même pas être mauvais!
nperson325681

15

Personne ne l'a encore suggéré, alors je le ferai: 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 tout ce qui va du HTML au hoquet , ClojureScript et l'une des milliards de bibliothèques JS dont vous avez besoin. Si vous vouliez un comportement de navigateur cohérent et un "look'n'feel" de l'application de bureau, vous pouvez regrouper Chrome avec votre application .

Cela semble être la façon dont Light Table est distribuée.


c'est génial, mais déterminer le bon port peut être difficile sur chaque machine client
scape

14

Depuis cette 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, il vaudrait la peine de regarder la section interopérabilité du site Web de clojure.


3
Ouais, je sais que vous pouvez utiliser Swing directement, mais je me suis demandé s'il y avait une manière plus douce de le faire.
Marko

Notez également que dans les versions les plus récentes de fermeture, vous devez ajouter un fichier. devant les appels de fonction membre dans le bloc todo.
Jeroen Dirks

8

Il existe un wrapper pour MigLayout dans clojure contrib. Vous pouvez également jeter un oeil à cet essentiel . Je suis en train de mettre en place le code que j'écris pendant que j'apprends le swing / miglayout.

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)))


6

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 la bascule, puis j'ai essayé un autre composant dans clojurefx.

J'ai terminé les deux et je suis convaincu que je vais refactoriser la bascule en clojurefx.

Après tout, JavaFX est la voie à suivre.

Il semble plus léger que la bascule. 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 en 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.


JavaFX a-t-il résolu le problème de ne pas avoir encore l'air très natif? Question sérieuse, car quand je l'ai vérifié pour la première fois, c'était il y a longtemps, et cela avait l'air moins correct que Swing.
Trejkaz

4

Voici un autre exemple très basique d'emballage de balançoire:

; 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)))

3

Je me suis posé la même question d'écrire une interface graphique dans Clojure avec Swing et j'ai trouvé le signe de la bibliothèque

Il vous permet de représenter votre modèle de domaine sous la forme d'une structure de données Clojure unique enveloppée dans un atome.

Voir les exemples ici .


2

J'ai développé une applet Java dans laquelle tout est écrit en Clojure sauf le code de l'applet, qui est écrit en Java. L'applet invoque les rappels du code Clojure de init, paint, etc. à partir des hooks de java pour les méthodes définies par le modèle de l'applet. Donc, le code finit par être Clojure à 99,999% et vous n'avez pas du tout à penser au petit morceau Java pour la plupart.

Il y a quelques inconvénients à cette approche, que j'espère discuter plus en détail sur le groupe Clojure Google. Je pense que les développeurs de Clojure devraient inclure une manière native de créer des applications. À l'heure actuelle, vous pouvez faire tout ce que vous voulez dans l'interface graphique à partir de la REPL, mais si vous voulez une application graphique livrable, il est nécessaire d'écrire du Java pour appeler le code Clojure. En outre, il semble que l'architecture d'une applet Java vous oblige à sortir des meilleures pratiques 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 que je n'ai tout simplement pas encore découvert comment le faire correctement.



2

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 dépôt 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.


1

Clojure et SWT est la meilleure approche pour faire des GUI. Essentiellement, SWT est une approche de style plug and play pour le développement de logiciels.


1
Pouvez-vous fournir un lien ou un exemple? Je serais intéressé mais je n'ai aucune idée de comment commencer.
Carl Smotricz

1
Carl, seconde cela. Un bon tutoriel sur la façon d'écrire des plugins Eclipse en utilisant clojure serait plutôt sympa.
Egon Willighagen

1

Je ne pense pas qu'il y ait de langage officiel, mais personnellement, je profiterais du fait que j'utilise l'un des langages les plus puissants au monde et imaginez à quoi ressemblerait le code d'interface graphique 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.


On dirait que le dsl SwingBuilder groovy traduit en Clojure.
Marko

@ dev-er-dev C'est très possible, je n'ai jamais utilisé groovy, mais les grands esprits font les choses de la même manière :)
tomjen

1

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 dans laquelle tout est connecté de sorte que si vous ajoutez de la musique au dossier audio, elle se reflète dans l'interface utilisateur Web. Dire simplement que l'application de bureau n'est pas le seul moyen :)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.