Вы правы. Swing - это путь, но соединение всех частей может быть немного жестким, если вы изучаете Clojure и Swing. Существует несколько коротких примеров, в которых показано, как создавать простые графические интерфейсы Swing в Clojure. Вот еще один короткий пример, который объединяет простой графический интерфейс с объектом Timer
.
(ns net.dneclark.JFrameAndTimerDemo
(:import (javax.swing JLabel JButton JPanel JFrame Timer))
(:gen-class))
(defn timer-action [label counter]
(proxy [java.awt.event.ActionListener] []
(actionPerformed
[e]
(.setText label (str "Counter: " (swap! counter inc))))))
(defn timer-fn []
(let [counter (atom 0)
label (JLabel. "Counter: 0")
timer (Timer. 1000 (timer-action label counter))
panel (doto (JPanel.)
(.add label))]
(.start timer)
(doto (JFrame. "Timer App")
(.setContentPane panel)
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(.setLocation 300 300)
(.setSize 200 200)
(.setVisible true))))
(defn -main []
(timer-fn))
При запуске это создаст небольшое окно с меткой, обновляемой каждую секунду. Из вашего описания вы измените частоту таймера от 1000 мс до 300 000 мс, чтобы активировать действие каждые 5 минут. Чтобы сделать что-то, кроме обновления метки, вы измените содержимое функции timer-action
.
I думаю это потокобезопасный, но не проверял. При обновлении компонентов Swing существуют предостережения и руководства по безопасности потоков. Вероятно, вы тоже захотите их проверить.
Надеюсь, это достаточно информативно, чтобы дать несколько подсказок относительно того, где искать дополнительную информацию.
EDIT: Я хотел указать еще одну интересную вещь здесь.Обратите внимание, что функция «timer-action» меняет значение одного из своих аргументов. Аргумент «counter» - это атом, определенный в «timer-fn», но прослушиватель действий может его изменить. Это то, что вы обычно не можете делать на Java. Может быть, кто-то умнее меня может прокомментировать, является ли это «закрытием». В моем предыдущем опыте с такими языками, как Pascal, я бы сказал, что передача аргумента является «вызовом по ссылке», в отличие от строгой передачи аргументов Java «по вызову». Это что-то другое?
EDIT 2: После проверки моих фактов другим вопросом, это, на самом деле, пример закрытия в Clojure.
+1 для предложений альтернатив. – trashgod
Хорошее начало, но вы полностью пропустили на качелях (https://github.com/daveray/seesaw), который выглядит так, что приложение будет значительно менее болезненным в Clojure. – deterb