Lucas Rudd
Lucas Rudd

Reputation: 415

Returning information from buttons in clojure/seesaw

I have another clojure question.

So I'm working on a project at the moment and attempting to write a GUI component for it. I have all the functional parts working, so now I just want it too look nice and learn a little more about how seesaw works.

Basically, I have a bunch of input fields (i.e. text fields, sliders, comboboxes) that the user can use to input certain types of data. When the user clicks the "confirm" button I want the button's action to return all the values of the aforementioned input fields. I don't have a lot of experience with threads but understand that (obviously) there may be some concurrency issues. How can I accomplish this?

For reference, here is a small sample of my code:

    ;
    ;in restaurant-gui.core
    ;

    (defn window-setup []
      (let [my-font        (font :name "Arial"
                                 :size 22)

           cuisine-label   (label    :text "Cuisine: "
                                     :font my-font
                                     :border [20 10])

           cuisine         (combobox :model["Any cuisine"
                                            "American"
                                            "Barbecue"
                                            "Chinese"
                                            "French"
                                            "Italian"])

           confirm-button  (button   :text "Confirm"
                                     :listen [:action (fn [event] event 
                           (selection cuisine))])

           window-contents (vertical-panel :items [cuisine-label cuisine 
                            confirm-button])]
           window-contents))

    ;     
    ;in restaurant-inference-engine.core
    ;

    (defn -main
      [&args]

      (binding [window-contents (window-setup)]
        (draw-window window-contents)     ;somehow listen here for
                                          ;information from the button
                                          ;and bind it to button-info?...

        (search-for-restaurant button-info)))

Also, if anyone knows of any simple to intermediate clojure code I could look at I would be very grateful. I would like to get more exposure to well-written clojure code to improve my understanding of the language.

Upvotes: 1

Views: 164

Answers (1)

Arthur Ulfeldt
Arthur Ulfeldt

Reputation: 91554

When working with inherently statefull things like GUIs there it's often helpful to turn to Clojure's mutable state features. I have seen two basic approaches:

  • store the state of each UI element in a ref and then pass the relevant refs into the functions that need to work on the state of the UI.
  • store the GUI's state in one atom and pass that atom to every function that uses any UI components so they can always use the current state of the UI at any time. Be careful to update it in consistent ways.
  • use core.async to have ui events send messages to the components that need them. This allows very responsive UI's with in my opinion clean code though you have to do the work of setting up the chans.

It seems unlikely that any one of these will work for all or even a majority of projects so it's bears some though on what your specific project will look like. You likely don't need to worry about "concurrency" issues if you stick to the official Clojure methods for working with changing state (atoms. vars, refs, agents, chans)

Upvotes: 1

Related Questions