简体   繁体   English

在 Clojure 中执行 GUI 的最佳方法是什么?

[英]What is the best way to do GUIs in Clojure?

What is the best way to do GUIs in Clojure ?Clojure 中执行 GUI 的最佳方法是什么?

Is there an example of some functional Swing or SWT wrapper?是否有一些功能性SwingSWT包装器的示例? Or some integration with JavaFX declarative GUI description which could be easily wrapped to s-expressions using some macrology?或者与JavaFX声明式 GUI 描述的一些集成,可以使用一些宏观轻松包装到s 表达式

Any tutorials?有教程吗?

I will humbly suggest Seesaw .我会虚心推荐跷跷板

Here's a REPL-based tutorial that assumes no Java or Swing knowledge.这是一个基于 REPL 的教程,假定没有 Java 或 Swing 知识。


Seesaw's a lot like what @tomjen suggests.跷跷板很像@tomjen 的建议。 Here's "Hello, World":这是“你好,世界”:

(use 'seesaw.core)

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

and here's @Abhijith and @dsm's example, translated pretty literally:这是@Abhijith 和@dsm 的例子,按字面翻译:

(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 recently published a series of blog posts on GUI-development with clojure (and swing). Stuart Sierra 最近发表了一系列关于使用 clojure(和 Swing)进行 GUI 开发的博客文章。 Start off here: http://stuartsierra.com/2010/01/02/first-steps-with-clojure-swing从这里开始: http : //stuartsierra.com/2010/01/02/first-steps-with-clojure-swing

If you want to do GUI programming I'd point to Temperature Converter or the ants colony .如果你想做 GUI 编程,我会指向Temperature Converterantscolony

Many things in Swing are done by sub-classing, particularly if you are creating custom components. Swing 中的许多事情都是通过子类化来完成的,尤其是在创建自定义组件时。 For that there are two essential functions/macros: proxy and gen-class .为此,有两个基本功能/宏: proxygen-class

Now I understand where you are going with the more Lispy way.现在我明白你用更多 Lispy 的方式去哪里了。 I don't think there's anything like that yet.我不认为有这样的事情。 I would strongly advise against trying to build a grandiose GUI-building framework a-la CLIM , but to do something more Lispy: start writing your Swing application and abstract out your common patterns with macros.我强烈建议不要尝试构建一个宏伟的 GUI 构建框架 a-la CLIM ,而是做更多 Lispy 的事情:开始编写您的 Swing 应用程序并使用宏抽象出您的常见模式。 When doing that you may end up with a language to write your kind of GUIs, or maybe some very generic stuff that can be shared and grow.这样做时,您可能最终会使用一种语言来编写您的 GUI,或者可能是一些可以共享和发展的非常通用的东西。

One thing you lose when writing the GUIs in Clojure is the use of tools like Matisse.在 Clojure 中编写 GUI 时您失去的一件事是使用了像 Matisse 这样的工具。 That can be a strong pointing to write some parts in Java (the GUI) and some parts in Clojure (the logic).用 Java(GUI)编写一些部分,用 Clojure(逻辑)编写一些部分,这可能是一个强有力的指示。 Which actually makes sense as in the logic you'll be able to build a language for your kind of logic using macros and I think there's more to gain there than with the GUI.这实际上是有道理的,因为在逻辑中,您将能够使用宏为您的逻辑类型构建一种语言,而且我认为在那里获得的比使用 GUI 还多。 Obviously, it depends on your application.显然,这取决于您的应用程序。

Nobody yet suggested it, so I will: Browser as UI platform.还没有人建议它,所以我会:浏览器作为 UI 平台。 You could write your app in Clojure, including an HTTP server and then develop the UI using anything from HTML to hiccup , ClojureScript and any of the billions of JS libaries you need.你可以写你的应用程序中的Clojure,包括HTTP服务器,然后使用任何从HTML开发UI打嗝,ClojureScript任何十亿JS的libaries你的需要。 If you wanted consistent browser behaviour and "desktop app look'n'feel" you could bundle chrome with your app .如果您想要一致的浏览器行为和“桌面应用程序外观”,您可以将chrome 与您的应用程序捆绑在一起

This seems to be how Light Table is distributed.这似乎是Light Table的分布方式。

From this 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");

And, of course, it would be worth looking at the interoperability section of clojure's website.而且,当然,值得查看 clojure 网站的互操作性部分。

There is a wrapper for MigLayout in clojure contrib.在 clojure contrib 中有一个 MigLayout 包装器。 You can also take a look at this gist .你也可以看看这个 gist I am basically putting up whatever code I am writing as I am learning swing/miglayout.在学习 Swing/miglayout 时,我基本上是在写我正在编写的任何代码。

dsm's example re-written in a lispy way using contrib.swing-utils dsm 的示例使用 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)))

I would rather go for clojurefx, it is a bit premature, but it does work and saves you time.我宁愿选择 clojurefx,这有点为时过早,但它确实有效并节省了您的时间。

I started my GUI with seesaw and then tried another component in clojurefx.我用跷跷板启动了我的 GUI,然后在 clojurefx 中尝试了另一个组件。

I have finished both, and I am convinced that I am going to refactor the seesaw one to clojurefx.我已经完成了两个,并且我确信我将把跷跷板重构为 clojurefx。

After all, JavaFX is the way to go forward.毕竟,JavaFX 是前进的道路。

It feels lighter than seesaw.感觉比跷跷板要轻。 Or at least, writing it..或者至少,写它..

Bindings work, listeners work, most of the component work, otherwise, just use one of the macros to create a constructor for that particular case and job done.绑定工作,侦听器工作,大部分组件工作,否则,只需使用宏之一为特定情况创建构造函数并完成工作。 Or, if you find it difficult, write some methods in Java and ask for help to improve clojurefx.或者,如果你觉得很难,用Java写一些方法并寻求帮助来改进clojurefx。

The guy who wrote clojurefx is busy at the moment, but you can fork the project and do some fixes.写 clojurefx 的人现在很忙,但你可以 fork 项目并做一些修复。

There's been talk on the mailing list about a few Cells (a la Kenny Tilton's Cells ) implementations. 邮件列表上已经讨论了一些 Cells(如Kenny Tilton 的 Cells )实现。 It's a pretty neat way to do GUI programming.这是进行 GUI 编程的一种非常巧妙的方式。

Here is another very basic swing wrapping example:这是另一个非常基本的摆动包装示例:

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

I asked myself the same question of writing a GUI in Clojure with Swing and came up with the library signe我问自己同样的问题,即在 Clojure 中用 Swing 编写 GUI 并想出了库签名

It lets you use represent your domain model as a single Clojure data structure wrapped inside an atom.它允许您将域模型表示为包裹在原子内的单个 Clojure 数据结构。

See the examples here .请参阅此处的示例。

我首选的 Clojure UI 环境使用IO.js (Node for ES6) + Electron (Container) + Quiescent (ReactJS wrapper)

So I didn't see Fn-Fx on this list, from Timothy Baldridge (halgiri).所以我没有在这个列表中看到来自 Timothy Baldridge (halgiri) 的 Fn-Fx。 This is a Clojure library providing a functional abstraction over JavaFX.这是一个 Clojure 库,提供对 JavaFX 的功能抽象。

It can be found on Github at https://github.com/halgari/fn-fx .它可以在 Github 上找到,网址为https://github.com/halgari/fn-fx

To use, make sure you are using a recent version of Java (1.8 90+) and add a dependency to the github repo by adding the following to your project.clj:要使用,请确保您使用的是最新版本的 Java (1.8 90+) 并通过将以下内容添加到您的 project.clj 来向 github 存储库添加依赖项:

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

I have tried it, and it works out of the box.我已经试过了,它开箱即用。

I've been developing a Java applet in which everything is written in Clojure except the applet code, which is written in Java.我一直在开发一个 Java 小程序,其中除了小程序代码是用 Java 编写的之外,所有内容都是用 Clojure 编写的。 The applet invokes the Clojure code's callbacks of init, paint, etc from java's hooks for those methods that are defined by the applet model.小程序从 Java 的钩子中为小程序模型定义的那些方法调用 Clojure 代码的 init、paint 等回调。 So the code ends up being 99.999 percent Clojure and you don't have to think about the tiny Java piece at all for the most part.因此,代码最终是 99.999% 的 Clojure,并且您在大多数情况下根本不必考虑小 Java 部分。

There are some drawbacks to this approach, which I hope to discuss in more detail on the Clojure Google Group.这种方法有一些缺点,我希望在 Clojure Google Group 上更详细地讨论。 I think the Clojure developers should include a native way of building applications.我认为 Clojure 开发人员应该包括构建应用程序的本机方式。 Presently you can do whatever GUI stuff you like from the REPL, but if you want a deliverable GUI application, it is necessary to write some Java to call the Clojure code.目前,您可以从 REPL 中执行任何您喜欢的 GUI 操作,但是如果您想要一个可交付的 GUI 应用程序,则需要编写一些 Java 来调用 Clojure 代码。 Also, it seems like the architecture of a Java Applet kind of forces you outside of Clojure's more idiomatic best practices, requiring you to use mutable state, etc.此外,似乎 Java Applet 的架构迫使您脱离 Clojure 更惯用的最佳实践,要求您使用可变状态等。

But also, I am not very far along with Clojure yet and it might be the case that it is possible and I just haven't discovered how to do it correctly yet.而且,我对 Clojure 的了解还不是很远,可能是这样,我只是还没有发现如何正确地做到这一点。

I don't think there is an official one, but personally I would take advantage of the fact that I am using one of the most powerful language in the world and just imagine what the perfect gui code would look like:我不认为有官方的,但我个人会利用我使用的是世界上最强大的语言之一这一事实,想象一下完美的 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})])

Your idea would differ but this should hopefully the above gives you some idea.你的想法会有所不同,但这应该希望以上能给你一些想法。

I know that you are hinting for classical desktop solutions, but web fits quite well with clojure.我知道你在暗示经典的桌面解决方案,但 web 非常适合 clojure。 I've written a complete audio application where everything is hooked up so that if you add music to the audio folder it is reflected in the web UI.我已经编写了一个完整的音频应用程序,其中所有内容都已连接,因此如果您将音乐添加到音频文件夹中,它会反映在 Web UI 中。 Just saying that Desktop application isn't the only way :)只是说桌面应用程序不是唯一的方法:)

Clojure and SWT is the best approach for doing GUI(s). Clojure 和 SWT 是制作 GUI 的最佳方法。 Essentially, SWT is a plug and play style approach for developing software.从本质上讲,SWT 是一种用于开发软件的即插即用风格的方法。

cljfx is described as a cljfx被描述为

Declarative, functional and extensible wrapper of JavaFX inspired by better parts of react and re-frame JavaFX 的声明性、功能性和可扩展包装器受到反应和重新框架的更好部分的启发

and JavaFx asJavaFx作为

... an open source, next generation client application platform for desktop, mobile and embedded systems built on Java. ... 一个开源的下一代客户端应用程序平台,适用于基于 Java 构建的桌面、移动和嵌入式系统。 It is a collaborative effort by many individuals and companies with the goal of producing a modern, efficient, and fully featured toolkit for developing rich client applications.这是许多个人和公司的共同努力,其目标是为开发富客户端应用程序开发一个现代、高效且功能齐全的工具包。

Its creator uses it to build reveal , and a hackernews demo that features various capabilities and some bundling for multiple OSs via jpackage .它的创作者用它来构建透露,和hackernews演示,具有不同的功能,并通过一些捆绑了多个操作系统JPackage上

You can get Clojure REPL-driven development with this by leveraging JavaFX to build UIs for desktop, mobile, and web.通过利用 JavaFX 为桌面、移动设备和 Web 构建 UI,您可以获得 Clojure REPL 驱动的开发。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM