Qual é a melhor maneira de fazer GUIs no Clojure?


150

Qual é a melhor maneira de fazer GUIs no Clojure ?

Existe um exemplo de algum wrapper Swing ou SWT funcional ? Ou alguma integração com a descrição declarativa da GUI do JavaFX que pode ser facilmente agrupada em expressões s usando alguma macrologia?

Algum tutorial?

Respostas:


121

Vou sugerir humildemente Gangorra .

Aqui está um tutorial baseado em REPL que não assume nenhum conhecimento sobre Java ou Swing.


Gangorra é muito parecido com o que sugere @tomjen. Aqui está "Olá, Mundo":

(use 'seesaw.core)

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

e aqui está o exemplo de @Abhijith e @ dsm, traduzido literalmente:

(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
tornando o Swing divertido? Eles disseram que não era possível!
Michael Bylstra

9
Não há necessidade de ser humilde - você pode ter muito orgulho disso! +1!
mydoghasworms

7
-1: existe um erro no seu código. Diz "Olá, Gangorra" em vez de "Olá, Mundo". </Joke>
Thomas Eding

1
Realmente? Balanço? Isso não limita o desenvolvedor à funcionalidade que o Swing oferece, apenas em um nível mais alto de abstração, se houver? O Clojure, de alguma forma, faz com que os aplicativos pareçam menos desatualizados ou melhora de alguma forma todas as áreas em que o Swing é fraco? Estou falando de ligações e MVC e todas essas coisas "novas", que o Swing agora oferece por si só. De alguma forma, é corrigido pelos recursos de idioma do Clojure?
Zelphir Kaltstahl

1
Ele escolheu fazer uma abstração focada sobre o Swing especificamente. Errado nada com isso ...
Kenogu Labz


16

Se você quiser fazer a programação da GUI, eu apontaria para o Temperature Converter ou a colônia de formigas .

Muitas coisas no Swing são feitas por subclassificação, principalmente se você estiver criando componentes personalizados. Para isso, existem duas funções / macros essenciais: proxy e gen-class .

Agora eu entendo para onde você está indo da maneira mais Lispy. Eu não acho que exista algo assim ainda. Eu desaconselharia fortemente a tentativa de criar uma estrutura grandiosa de criação de GUI à la CLIM , mas para fazer algo mais Lispy: comece a escrever seu aplicativo Swing e abstraia seus padrões comuns com macros. Ao fazer isso, você pode acabar com um idioma para escrever seu tipo de GUI, ou talvez algo muito genérico que possa ser compartilhado e aumentado.

Uma coisa que você perde ao escrever as GUIs no Clojure é o uso de ferramentas como o Matisse. Isso pode ser um forte argumento para escrever algumas partes em Java (a GUI) e algumas partes em Clojure (a lógica). O que realmente faz sentido, pois na lógica você poderá criar uma linguagem para seu tipo de lógica usando macros e acho que há mais a ganhar lá do que com a GUI. Obviamente, isso depende da sua aplicação.


2
Não se preocupe em perder Mattisse. Você pode usar o miglayout.com , que é poderoso o suficiente para fazer os layouts manualmente.
tomjen

Você pode usar o Matisse com o Clojure, porque o código gerado é apenas o código Java que pode ser acessado facilmente pelo Clojure. Há realmente um tutorial para que em algum lugar ...
Rayne

3
Gostaria de saber quando obteremos o primeiro designer de GUI com saída de clojure. Devido à homoiconicidade, o código gerado nem deve ser ruim!
nperson325681

15

Ninguém o sugeriu ainda, então vou: Navegador como plataforma de interface do usuário. Você pode escrever seu aplicativo no Clojure, incluindo um servidor HTTP e, em seguida, desenvolver a interface do usuário usando qualquer coisa, desde HTML a soluços , ClojureScript e qualquer um dos bilhões de bibliotecas JS necessárias. Se você quiser um comportamento consistente do navegador e "aparência do aplicativo de desktop", poderá agrupar o chrome no seu aplicativo .

Parece que é assim que a Light Table é distribuída.


isso é ótimo, mas determinar a porta apropriada pode ser complicado em cada máquina cliente
scape

14

Nesta página :

(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, é claro, valeria a pena examinar a seção de interoperabilidade do site da clojure.


3
Sim, eu sei que você pode voltar a usar o Swing diretamente, mas perguntei se há uma maneira mais fácil de fazê-lo.
264 Marko

Observe também que nas versões mais recentes do fechamento você precisa adicionar um. na frente da função de membro chama no bloco de tarefas.
Jeroen Dirks

8

Existe um invólucro para o MigLayout no controj clojure. Você também pode dar uma olhada nessa essência . Basicamente, estou colocando o código que estou escrevendo enquanto aprendo swing / miglayout.

O exemplo do dsm reescrito de uma maneira lispy 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

Eu prefiro usar o clojurefx, é um pouco prematuro, mas funciona e economiza tempo.

Comecei minha GUI com gangorra e tentei outro componente no clojurefx.

Eu terminei os dois e estou convencido de que vou refatorar a gangorra para clojurefx.

Afinal, JavaFX é o caminho a seguir.

Parece mais leve que gangorra. Ou pelo menos, escrevendo ..

As ligações funcionam, os ouvintes funcionam, a maioria dos componentes funciona; caso contrário, basta usar uma das macros para criar um construtor para esse caso e trabalho específico. Ou, se você achar difícil, escreva alguns métodos em Java e peça ajuda para melhorar o clojurefx.

O cara que escreveu o clojurefx está ocupado no momento, mas você pode bifurcar o projeto e fazer algumas correções.


O JavaFX resolveu os problemas de não parecer muito nativo ainda? Pergunta séria, porque quando fiz o check-out pela primeira vez, isso foi há muito tempo e parecia menos correto que o Swing.
Trejkaz

4

Aqui está outro exemplo muito básico de empacotamento de giro:

; 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

Eu me perguntei a mesma questão de escrever uma GUI no Clojure com Swing e criei o signe da biblioteca

Ele permite que você represente seu modelo de domínio como uma única estrutura de dados Clojure agrupada dentro de um átomo.

Veja os exemplos aqui .


2

Estou desenvolvendo um applet Java no qual tudo está escrito no Clojure, exceto o código do applet, que está escrito em Java. O applet chama os retornos de chamada do código Clojure, init, paint, etc, dos ganchos do java para os métodos definidos pelo modelo do applet. Portanto, o código acaba sendo 99,999% do Clojure e você não precisa pensar na menor parte do Java na maior parte do tempo.

Existem algumas desvantagens nessa abordagem, que espero discutir com mais detalhes no Clojure Google Group. Eu acho que os desenvolvedores do Clojure devem incluir uma maneira nativa de criar aplicativos. Atualmente, você pode fazer qualquer coisa da GUI do REPL, mas se você quiser um aplicativo de GUI entregável, é necessário escrever um pouco de Java para chamar o código Clojure. Além disso, parece que a arquitetura de um Java Applet o força fora das práticas recomendadas mais idiomáticas do Clojure, exigindo o uso de estado mutável etc.

Mas também não estou muito longe com Clojure e pode ser que seja possível e simplesmente não descobri como fazê-lo corretamente ainda.



2

Então eu não vi Fn-Fx nesta lista, de Timothy Baldridge (halgiri). Esta é uma biblioteca Clojure que fornece uma abstração funcional sobre JavaFX.

Pode ser encontrado no Github em https://github.com/halgari/fn-fx .

Para usar, verifique se você está usando uma versão recente do Java (1.8 90+) e adicione uma dependência ao repositório do github adicionando o seguinte ao seu projeto.clj:

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

Eu tentei, e funciona fora da caixa.


1

Clojure e SWT são a melhor abordagem para fazer GUI (s). Essencialmente, o SWT é uma abordagem de estilo plug and play para o desenvolvimento de software.


1
Você pode fornecer um link ou um exemplo? Eu estaria interessado, mas não tenho idéia de como começar.
22630 Carl Smotricz

1
Carl, segundo isso. Um bom tutorial sobre como escrever plugins do Eclipse usando o clojure seria muito bom.
Egon Willighagen

1

Eu não acho que exista um oficial, mas pessoalmente eu aproveitaria o fato de estar usando uma das línguas mais poderosas do mundo e apenas imagino como seria o código da GUI perfeito:

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

Sua idéia seria diferente, mas espero que o acima tenha uma idéia.


Parece dsl SwingBuilder groovy traduzido para Clojure.
Marko

@ dev-er-dev Isso é muito possível, eu nunca usei groovy, mas as grandes mentes fazer coisa tanto :)
tomjen

1

Sei que você está sugerindo soluções clássicas de desktop, mas a web se encaixa muito bem com o clojure. Eu escrevi um aplicativo de áudio completo, onde tudo está conectado, de modo que, se você adicionar música à pasta de áudio, ela será refletida na interface da web. Apenas dizendo que o aplicativo de desktop não é o único caminho :)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.