[racket] Run Code after Button Click using the racket/gui library

From: Derek C. (puzzledplane at yahoo.com)
Date: Mon Oct 27 20:46:18 EDT 2014

Hello,


Thank you for the reply. It was very helpful. 


The only thing that I am confused in doing now is that I have to store the value of the zip code in order to use it within the API’s url. That is the first thing I was trying to do because I need to take the zip code that is entered and be able to add it within the url before the .xml extension. 


For Example: http://api.wunderground.com/api/*snip*/conditions/q/ZIPCODE.xml

where ZIPCODE is the zip code that was entered.


At first, I was attempting to get this value from the zipcodelabel message% object, using (define x (send zipcodelabel get-label)) but that would only give me the initial value of the message% which is "No Zip Code Entered".


Thanks again,

Puzzledplane






From: Matthias Felleisen
Sent: ‎Monday‎, ‎October‎ ‎27‎, ‎2014 ‎1‎:‎56‎ ‎PM
To: Derek C.
Cc: users at racket-lang.org







On Oct 26, 2014, at 5:51 PM, Derek C. wrote:



I am trying to get the value of a label after a button is clicked. I know that I can use (send x get-label) to get the value of the label, but it only gets the initial value of the label in my case "No Zip Code Entered".




I don't know what you are asking. When I enter a zip code and click Submit, the zip code shows up in your text field. 






Also, after that button is pressed I would like to run code that queries an API and parses xml information using the zip code from the label. Below is my code:


See below. I have marked some small changes and sketched a way to get this going. I also fixed some basic style issues. 




Note: if this is homework, please forward the assignment so we can help more directly. If not, I recommend developing with testing in mind (see rackunit and submodules). 




-- Matthias















#lang racket




(require racket/gui/base)




;; -> Void 

(define (main) ;; don't run directly, wrap in main function from the beginning; work with (module+ main ...) if you want to always run 

  

  ;; Creates a Frame called mainframe

  (define mainframe 

    (new frame%

         [label "Forecaster - Powered by Wunderground API"]

         [width 500]

         [height 500]

         [stretchable-width 500]

         [stretchable-height 500]))

  

  ;; Creates a Current Conditions group-box-panel

  (define maingroup

    (new group-box-panel%

         [label "Current Conditions:"]

         [parent mainframe]

         [min-height 450]

         [stretchable-height 450]))

  

  (define cclabel-text (new text%)) ; you want a editor here, not a message 

  [send cclabel-text insert "Insert Conditions Here from API"] ;; add your initial string, though I am not sure what for 

  (define cclabel  ;; now put the editor into a canvas

    (new editor-canvas%

         [parent maingroup]

         [label "current conditions"]

         [editor cclabel-text]))

  

  ;; Creates a Zip Code group-box-panel

  (define zipcodegroup 

    (new group-box-panel%

         [label "Zip Code:"]

         [parent mainframe]

         [min-height 100]

         [stretchable-height 100]))

  

  ;; Zip Code Message Label -- Defaults to No Zip Code Entered

  (define zipcodelabel

    (new message%

         [parent zipcodegroup]

         [label "No Zip Code Entered"] ))

  

  ;; Zip Code Text-Field

  (define zipInput 

    (new text-field% 

         [parent zipcodegroup]

         [label ""]

         [init-value ""]

         [min-width 5]

         [stretchable-width 5]

         [callback

          (lambda(f ev)

            (define v (send f get-value))

            (unless (string->number v)

              (send f set-value (regexp-replace* #rx"[^0-9]+" v ""))))]))

  

  ;; Submit Button

  (define submit-button 

    (new button% 

         [parent zipcodegroup]

         [label "Submit"]

         [callback  

          (lambda (button event)

            ;; use internal define over let only because it's easier

            (define zip-code (send zipInput get-value))

            (define weather  (retrieve zip-code))

            (send zipcodelabel set-label zip-code)

            ;; now insert weather into the editor, but clear it first 

            (send cclabel-text select-all)

            (send cclabel-text clear)

            (send cclabel-text insert (prepare-as-text weather)))]))

  ;; -- IN -- 

  (send mainframe show #t))  




;; helper but this may actually have to work on the editor directly to make it look good 

(define (prepare-as-text list-of-pairs)

  (string-join 

   (map (lambda (x) (format "~a ~a" (first x) (second x))) list-of-pairs)

   "\n"))




;XML Parsing:

;

;#lang racket




;; this module should presumably provide a retrieve function that does the hard work: 

;; (provide 

;;    ; ZipCode -> [Listof [List Symbol String]]

;;    ; retrieve the information for the given zip code and deliver the result as an association list 

;;    ; -- examples here -- 

;;    retrieve)

(require net/url xml xml/path)




(define underground-url-format

  "http://api.wunderground.com/api/*snip*/conditions/q/autoip.xml")




;; I am taking a short-cut here: 

(define (retrieve zip-code)

  (list (list 'Location: "Boston, MA") (list 'Conditions: "typical fall day") 

        (list 'Temperature: "57o F")   (list 'Feels-Like: "damp, humid, earthy")

        (list 'Humidity: "67%")        (list 'Wind: "5mph, south-by-south-west")))




(define (retrieve-to-be-done zip-code)  

  (define curent-cond-url (string->url (format underground-url-format zip-code)))

  (define current-cond-port (get-pure-port curent-cond-url))

  (define response (port->string current-cond-port))

  (close-input-port current-cond-port)

  

  (define data (xml->xexpr

                ((eliminate-whitespace '(response))

                 (read-xml/element (open-input-string response)))))

  

  (define curr-location (se-path*/list '(display_location full) data))

  (define curr-weather (se-path*/list '(current_observation weather) data))

  (define curr-temp (se-path*/list '(current_observation temp_f) data))

  (define curr-humidity (se-path*/list '(current_observation relative_humidity) data))

  (define curr-wind (se-path*/list '(current_observation wind_string) data))

  (define curr-feels-like (se-path*/list '(current_observation feelslike_f) data))

  

  (list (list 'Location: curr-location) (list 'Conditions: curr-weather) 

        (list 'Temperature: curr-temp)  (list 'Feels-Like: curr-feels-like)

        (list 'Humidity: curr-humidity) (list 'Wind: curr-wind)))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20141028/a40d4dfa/attachment-0001.html>

Posted on the users mailing list.