Was ist der beste Weg, um GUIs in Clojure zu machen?


Antworten:


121

Ich werde demütig Seesaw vorschlagen .

Hier ist ein REPL-basiertes Tutorial , das keine Java- oder Swing-Kenntnisse voraussetzt.


Seesaw ist sehr ähnlich zu dem, was @tomjen vorschlägt. Hier ist "Hallo Welt":

(use 'seesaw.core)

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

und hier ist das Beispiel von @Abhijith und @ dsm, wörtlich übersetzt:

(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
Swing zum Spaß machen? Sie sagten, es sei nicht möglich!
Michael Bylstra

9
Sie müssen nicht demütig sein - Sie können sehr stolz auf diesen sein! +1!
Mydoghaswürmer

7
-1: Ihr Code enthält einen Fehler. Es heißt "Hallo, Wippe" statt "Hallo, Welt". </ Joke>
Thomas Eding

1
"Ja wirklich?" Schwingen? Beschränkt dies den Entwickler nicht auf die Funktionalität, die Swing bietet, nur auf einer höheren Abstraktionsebene, wenn überhaupt? Lässt Clojure die Anwendungen irgendwie weniger veraltet aussehen oder verbessert es irgendwie alle Bereiche, in denen Swing schwach ist? Ich spreche von Bindungen und MVC und all dem "neuen" Zeug, das Swing jetzt per se anbietet. Wird es irgendwie durch Sprachfunktionen von Clojure behoben?
Zelphir Kaltstahl

1
Er entschied sich für eine gezielte Abstraktion über Swing. Daran ist nichts auszusetzen ...
Kenogu Labz


16

Wenn Sie eine GUI-Programmierung durchführen möchten, würde ich auf Temperature Converter oder die Ameisenkolonie verweisen .

Viele Dinge in Swing werden durch Unterklassifizierung erledigt, insbesondere wenn Sie benutzerdefinierte Komponenten erstellen. Dafür gibt es zwei wesentliche Funktionen / Makros: Proxy und Gen-Klasse .

Jetzt verstehe ich, wohin du mit dem lispy Weg gehst. Ich glaube, so etwas gibt es noch nicht. Ich würde dringend davon abraten, ein grandioses GUI-Framework a-la- CLIM zu erstellen zu erstellen, aber etwas Lispigeres zu tun: Schreiben Sie Ihre Swing-Anwendung und abstrahieren Sie Ihre allgemeinen Muster mit Makros. Wenn Sie dies tun, erhalten Sie möglicherweise eine Sprache, in der Sie Ihre Art von GUIs schreiben können, oder vielleicht einige sehr allgemeine Dinge, die geteilt werden und wachsen können.

Eine Sache, die Sie beim Schreiben der GUIs in Clojure verlieren, ist die Verwendung von Tools wie Matisse. Dies kann ein starker Hinweis darauf sein, einige Teile in Java (die GUI) und einige Teile in Clojure (die Logik) zu schreiben. Was tatsächlich Sinn macht, da Sie in der Logik mithilfe von Makros eine Sprache für Ihre Art von Logik erstellen können, und ich denke, dass es dort mehr zu gewinnen gibt als mit der GUI. Natürlich hängt es von Ihrer Anwendung ab.


2
Mach dir keine Sorgen, Mattisse zu verlieren. Sie können miglayout.com verwenden , das leistungsstark genug ist, um die Layouts von Hand zu erstellen.
Tomjen

Sie können Matisse mit Clojure verwenden, da der generierte Code nur Java-Code ist, auf den Clojure nahtlos zugreifen kann. Es gibt tatsächlich irgendwo ein Tutorial dafür ...
Rayne

3
Ich frage mich, wann wir den ersten GUI-Designer mit Clojure-Ausgabe bekommen. Aufgrund der Homoikonizität sollte der generierte Code nicht einmal schlecht sein!
nperson325681

15

Noch hat es niemand vorgeschlagen, also werde ich: Browser als UI-Plattform. Sie können Ihre App in Clojure schreiben, einschließlich eines HTTP-Servers, und dann die Benutzeroberfläche mit HTML, Schluckauf , ClojureScript und den Milliarden von JS-Bibliotheken entwickeln, die Sie benötigen. Wenn Sie ein konsistentes Browserverhalten und "Desktop-App-Look'n'Feel" wünschen, können Sie Chrome mit Ihrer App bündeln .

So scheint Light Table verteilt zu sein.


Das ist großartig, aber die Bestimmung des richtigen Ports kann auf jedem Client-Computer schwierig sein
Scape

14

Von dieser Seite :

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

Und natürlich lohnt es sich, den Abschnitt zur Interoperabilität auf der Website von clojure zu lesen.


3
Ja, ich weiß, dass Sie direkt auf Swing zurückgreifen können, aber ich habe gefragt, ob es einen lispigeren Weg gibt, dies zu tun.
Marko

Beachten Sie auch, dass Sie in den neueren Versionen von Closure a hinzufügen müssen. vor dem Element Funktionsaufrufe im Aufgabenblock.
Jeroen Dirks

8

Es gibt einen Wrapper für MigLayout in Clojure Contrib. Sie können sich auch dieses Wesentliche ansehen . Ich stelle im Grunde den Code auf, den ich schreibe, während ich Swing / Miglayout lerne.

Das Beispiel von dsm wurde mit Contrib.swing-Utils lispy neu geschrieben

(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

Ich würde mich lieber für Clojurefx entscheiden, es ist etwas verfrüht, aber es funktioniert und spart Ihnen Zeit.

Ich habe meine GUI mit Wippe gestartet und dann eine andere Komponente in clojurefx ausprobiert.

Ich habe beide beendet und bin überzeugt, dass ich die Wippe zu Clojurefx umgestalten werde.

Schließlich ist JavaFX der richtige Weg.

Es fühlt sich leichter an als Wippe. Oder zumindest schreiben ..

Bindungen funktionieren, Listener funktionieren, die meisten Komponenten funktionieren, andernfalls verwenden Sie einfach eines der Makros, um einen Konstruktor für diesen speziellen Fall und die erledigte Arbeit zu erstellen. Wenn Sie Schwierigkeiten haben, schreiben Sie einige Methoden in Java und bitten Sie um Hilfe, um clojurefx zu verbessern.

Der Typ, der clojurefx geschrieben hat, ist gerade beschäftigt, aber Sie können das Projekt abspalten und einige Korrekturen vornehmen.


Hat JavaFX die Probleme gelöst, noch nicht sehr nativ auszusehen? Ernsthafte Frage, denn als ich es zum ersten Mal auscheckte, war es lange her und es sah weniger richtig aus als Swing.
Trejkaz

4

Hier ist ein weiteres sehr einfaches Beispiel für Swing Wrapping:

; 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

Ich stellte mir die gleiche Frage, wie ich in Clojure mit Swing eine grafische Benutzeroberfläche schreiben sollte, und kam auf die Signatur der Bibliothek

Sie können Ihr Domänenmodell als einzelne Clojure-Datenstruktur darstellen, die in ein Atom eingeschlossen ist.

Siehe die Beispiele hier .


2

Ich habe ein Java-Applet entwickelt, in dem alles in Clojure geschrieben ist, außer dem Applet-Code, der in Java geschrieben ist. Das Applet ruft die Rückrufe des Clojure-Codes von init, paint usw. aus den Java-Hooks für die vom Applet-Modell definierten Methoden auf. Der Code lautet also zu 99,999 Prozent Clojure, und Sie müssen größtenteils überhaupt nicht an das winzige Java-Teil denken.

Dieser Ansatz weist einige Nachteile auf, die ich hoffentlich in der Clojure Google Group ausführlicher erläutern werde. Ich denke, die Clojure-Entwickler sollten eine native Methode zum Erstellen von Anwendungen einbeziehen. Gegenwärtig können Sie mit der REPL beliebige GUI-Aufgaben ausführen. Wenn Sie jedoch eine lieferbare GUI-Anwendung wünschen, müssen Sie Java schreiben, um den Clojure-Code aufzurufen. Außerdem scheint es so, als würde Sie die Architektur eines Java-Applets außerhalb der idiomatischeren Best Practices von Clojure zwingen, sodass Sie einen veränderlichen Status usw. verwenden müssen.

Aber auch mit Clojure bin ich noch nicht weit und es könnte sein, dass dies möglich ist und ich noch nicht herausgefunden habe, wie ich es richtig machen soll.



2

Also habe ich Fn-Fx von Timothy Baldridge (halgiri) auf dieser Liste nicht gesehen. Dies ist eine Clojure-Bibliothek, die eine funktionale Abstraktion über JavaFX bietet.

Es kann auf Github unter https://github.com/halgari/fn-fx gefunden werden .

Stellen Sie zur Verwendung sicher, dass Sie eine aktuelle Version von Java (1.8 90+) verwenden, und fügen Sie dem Github-Repo eine Abhängigkeit hinzu, indem Sie Ihrer project.clj Folgendes hinzufügen:

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

Ich habe es versucht, und es funktioniert sofort.


1

Clojure und SWT sind der beste Ansatz für GUI (s). Im Wesentlichen ist SWT ein Plug-and-Play-Ansatz für die Entwicklung von Software.


1
Können Sie einen Link oder ein Beispiel angeben? Ich wäre interessiert, hätte aber keine Ahnung, wie ich anfangen soll.
Carl Smotricz

1
Carl, zweitens. Ein gutes Tutorial zum Schreiben von Eclipse-Plugins mit Clojure wäre ziemlich nett.
Egon Willighagen

1

Ich glaube nicht, dass es eine offizielle gibt, aber ich persönlich würde die Tatsache ausnutzen, dass ich eine der mächtigsten Sprachen der Welt verwende und mir nur vorstellen, wie der perfekte GUI-Code aussehen würde:

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

Ihre Idee würde sich unterscheiden, aber dies sollte Ihnen hoffentlich eine Vorstellung davon geben.


Sieht aus wie groovy SwingBuilder dsl übersetzt in Clojure.
Marko

@ dev-er-dev Das ist sehr gut möglich, ich habe noch nie groovig verwendet, aber große Köpfe machen das Gleiche :)
Tomjen

1

Ich weiß, dass Sie auf klassische Desktop-Lösungen hinweisen, aber das Web passt recht gut zu Clojure. Ich habe eine vollständige Audioanwendung geschrieben, in der alles angeschlossen ist, sodass Musik, die Sie dem Audioordner hinzufügen, in der Web-Benutzeroberfläche angezeigt wird. Nur zu sagen, dass Desktop-Anwendung nicht der einzige Weg ist :)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.