Qual è il modo migliore per fare le GUI in Clojure?


150

Qual è il modo migliore per fare le GUI in Clojure ?

C'è un esempio di alcuni wrapper Swing o SWT funzionali ? O qualche integrazione con la descrizione della GUI dichiarativa di JavaFX che potrebbe essere facilmente inclusa nelle espressioni s usando un po 'di macrologia?

Qualche tutorial?

Risposte:


121

Suggerirò umilmente il movimento alternato .

Ecco un tutorial basato su REPL che non presuppone alcuna conoscenza di Java o Swing.


L'altalena è molto simile a ciò che suggerisce @tomjen. Ecco "Ciao, mondo":

(use 'seesaw.core)

(-> (frame :title "Hello"
       :content "Hello, Seesaw"
       :on-close :exit)
  pack!
  show!)

ed ecco l'esempio di @Abhijith e @ dsm, tradotto letteralmente:

(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
rendere Swing divertente? Dissero che non era possibile!
Michael Bylstra, il

9
Non c'è bisogno di essere umili - puoi esserne molto orgoglioso! +1!
mydoghasworms

7
-1: c'è un bug nel tuo codice. Dice "Ciao, movimento alternato" invece di "Ciao, mondo". </Joke>
Thomas Eding,

1
Veramente? Swing? Questo non limita lo sviluppatore alle funzionalità offerte da Swing, solo su un livello più alto di astrazione, se ce ne sono? Clojure in qualche modo rende le applicazioni meno datate o migliora in qualche modo tutte le aree in cui Swing è debole? Sto parlando di attacchi e MVC e di tutte quelle "nuove" cose, che Swing ora offre di per sé. È in qualche modo corretto dalle caratteristiche linguistiche di Clojure?
Zelphir Kaltstahl,

1
Ha scelto di fare un'astrazione focalizzata su Swing in particolare. Niente di male in questo ...
Kenogu Labz,


16

Se si desidera eseguire la programmazione della GUI, sceglierei Convertitore di temperatura o la colonia di formiche .

Swing esegue molte operazioni in subclasse, in particolare se si creano componenti personalizzati. Per questo ci sono due funzioni / macro essenziali: proxy e gen-class .

Ora capisco dove stai andando con il modo più Lispy. Non credo ci sia ancora niente del genere. Consiglio vivamente di non provare a costruire un grandioso framework di costruzione di GUI alla CLIM , ma di fare qualcosa di più Lispy: iniziare a scrivere l'applicazione Swing e astrarre i tuoi schemi comuni con le macro. Quando lo fai potresti finire con una lingua per scrivere il tuo tipo di GUI, o forse alcune cose molto generiche che possono essere condivise e crescere.

Una cosa che perdi quando scrivi le GUI in Clojure è l'uso di strumenti come Matisse. Questo può essere un punto forte per scrivere alcune parti in Java (la GUI) e alcune parti in Clojure (la logica). Il che in realtà ha senso come nella logica sarai in grado di costruire un linguaggio per il tuo tipo di logica usando le macro e penso che ci sia di più da guadagnare rispetto alla GUI. Ovviamente, dipende dalla tua applicazione.


2
Non preoccuparti di perdere Mattisse. Puoi usare miglayout.com , che è abbastanza potente da poter eseguire manualmente i layout.
tomjen,

Puoi usare Matisse con Clojure, perché il codice generato è solo codice Java a cui Clojure può accedere senza problemi. In realtà c'è un tutorial per questo da qualche parte ...
Rayne,

3
Mi chiedo quando avremo il primo designer di GUI che emette clojure. A causa dell'omoiconicità, il codice generato non dovrebbe nemmeno essere cattivo!
nperson325681

15

Nessuno l'ha ancora suggerito, quindi lo farò: Browser come piattaforma UI. Potresti scrivere la tua app in Clojure, incluso un server HTTP e quindi sviluppare l'interfaccia utente usando qualsiasi cosa, dall'HTML al singhiozzo , ClojureScript e uno qualsiasi dei miliardi di librerie JS di cui hai bisogno. Se desideri un comportamento coerente del browser e "look'n'feel" per app desktop, puoi raggruppare Chrome con la tua app .

Questo sembra essere il modo in cui è distribuito Light Table .


questo è fantastico, ma determinare la porta corretta può essere complicato su ogni macchina client
scape

14

Da questa pagina :

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

E, naturalmente, sarebbe la pena di guardare l' interoperabilità sezione del sito web di clojure.


3
Sì, so che puoi ricorrere all'utilizzo diretto di Swing, ma mi chiedevo se esiste un modo più semplice di farlo.
Marko,

Si noti inoltre che nelle versioni più recenti di chiusura è necessario aggiungere un. davanti alla funzione membro chiama nel blocco todo.
Jeroen Dirks,

8

C'è un wrapper per MigLayout nel clojure contrib. Puoi anche dare un'occhiata a questo riassunto . Fondamentalmente sto mettendo qualunque codice sto scrivendo mentre sto imparando swing / miglayout.

L'esempio di dsm riscritto in modo chiaro usando 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

Preferirei optare per clojurefx, è un po 'prematuro, ma funziona e ti fa risparmiare tempo.

Ho iniziato la mia GUI con l'altalena e poi ho provato un altro componente in clojurefx.

Ho finito entrambi e sono convinto che rifatterò il movimento alternato in clojurefx.

Dopotutto, JavaFX è la strada da percorrere.

Sembra più leggero del movimento alternato. O almeno, scrivendolo ..

I collegamenti funzionano, i listener funzionano, la maggior parte dei componenti funziona, altrimenti, basta usare una delle macro per creare un costruttore per quel particolare caso e lavoro svolto. Oppure, se lo trovi difficile, scrivi alcuni metodi in Java e chiedi aiuto per migliorare clojurefx.

Il ragazzo che ha scritto clojurefx al momento è impegnato, ma puoi biforcare il progetto e fare alcune correzioni.


JavaFX ha risolto i problemi di non sembrare ancora molto nativo? Domanda seria, perché quando l'ho verificato per la prima volta, è stato tanto tempo fa e sembrava meno corretto di Swing.
Trejkaz,

4

Ecco un altro esempio di avvolgimento altalena molto semplice:

; 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

Mi sono posto la stessa domanda di scrivere una GUI in Clojure con Swing e ho pensato alla biblioteca firma

Ti consente di rappresentare il tuo modello di dominio come un'unica struttura di dati Clojure racchiusa in un atomo.

Vedi gli esempi qui .


2

Ho sviluppato un'applet Java in cui tutto è scritto in Clojure tranne il codice dell'applet, che è scritto in Java. L'applet richiama i callback del codice Clojure di init, paint, ecc. Dagli hook di java per quei metodi che sono definiti dal modello dell'applet. Quindi il codice finisce per essere Clojure al 99,999 per cento e per la maggior parte non devi assolutamente pensare al minuscolo pezzo di Java.

Ci sono alcuni svantaggi di questo approccio, che spero di discutere in modo più dettagliato sul gruppo Google Clojure. Penso che gli sviluppatori di Clojure dovrebbero includere un modo nativo di creare applicazioni. Al momento puoi fare qualsiasi cosa GUI ti piaccia dalla REPL, ma se vuoi un'applicazione GUI consegnabile, è necessario scrivere un po 'di Java per chiamare il codice Clojure. Inoltre, sembra che l'architettura di un tipo di applet Java ti costringa al di fuori delle migliori pratiche più idiomatiche di Clojure, richiedendo l'uso di uno stato mutabile, ecc.

Inoltre, non sono ancora molto vicino a Clojure e potrebbe essere il caso che sia possibile e non ho ancora scoperto come farlo correttamente.



2

Quindi non ho visto Fn-Fx in questa lista, da Timothy Baldridge (algiri). Questa è una libreria Clojure che fornisce un'astrazione funzionale su JavaFX.

È disponibile su Github all'indirizzo https://github.com/halgari/fn-fx .

Per usarlo, assicurati di utilizzare una versione recente di Java (1.8 90+) e aggiungi una dipendenza al repository github aggiungendo quanto segue a project.clj:

:plugins [[lein-git-deps "0.0.1-SNAPSHOT"]]
:git-dependencies [["https://github.com/halgari/fn-fx.git"]]

L'ho provato e funziona subito.


1

Clojure e SWT è l'approccio migliore per eseguire le GUI. Fondamentalmente, SWT è un approccio plug and play per lo sviluppo di software.


1
Puoi fornire un link o un esempio? Sarei interessato ma non ho idea di come iniziare.
Carl Smotricz,

1
Carl, secondo quello. Un buon tutorial su come scrivere plugin Eclipse usando clojure sarebbe piuttosto carino.
Egon Willighagen,

1

Non penso che ce ne sia uno ufficiale, ma personalmente trarrei vantaggio dal fatto che sto usando una delle lingue più potenti al mondo e immagino solo come sarebbe il perfetto codice gui:

(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})])

La tua idea sarebbe diversa ma questo dovrebbe sperare che quanto sopra ti dia qualche idea.


Sembra Groovy SwingBuilder dsl tradotto in Clojure.
Marko,

@ dev-er-dev Questo è molto possibile, non ho mai usato groovy, ma le grandi menti fanno le
stesse

1

So che stai suggerendo soluzioni desktop classiche, ma il web si adatta abbastanza bene al clojure. Ho scritto un'applicazione audio completa in cui tutto è collegato in modo tale che se aggiungi musica alla cartella audio si rifletta nell'interfaccia utente web. Sto solo dicendo che l'applicazione desktop non è l'unico modo :)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.