How to avoid circular definition in racket language - user-interface

I tried to write simple gui to modify it’s text then copy it's content to text2.
But the call function can't be defined because its owner (text) is not defined yet.
This is the warning :
"cannot reference an identifier before its definition"
Is there anyway I could either:
assign callback later?
avoid circular reference?
Below is the code :
#lang racket/gui
(define toplevel (new frame% [label "MD View"] [width 800] [height 300]))
(define canvas (new editor-canvas% [parent toplevel] [style '(no-hscroll)]))
(define canvas2 (new editor-canvas% [parent toplevel] [style '(no-hscroll)]))
(define text2 (new text%))
(define text (new text%
[callback (send text2 insert (send text get-text)) ]
)) ;; warning here
(send canvas set-editor text)
(send canvas2 set-editor text2)
(send text auto-wrap #t)
(send text set-padding 10 10 10 10)
(send text2 auto-wrap #t)
(send text2 set-padding 10 10 10 10)
(new button% [parent toplevel]
[label "write"]
; Callback procedure for a button click:
[callback (lambda (button event)
(send text2 insert "written"))])
(new button% [parent toplevel]
[label "copy"]
; Callback procedure for a button click:
[callback (lambda (button event)
(send text2 insert (send text get-text)))])
(send toplevel show #t)

Related

Racket GUI Toolkit: How to embed a link

Say we have a frame
(define my-frame (new frame% [parent #f] [label "test"]))
and a message, that should link to google.
(new message%
[parent my-frame]
[label "https://www.google.com"])
(send my-frame show #t)
The above does not work. How does one embed a link in the Racket GUI toolkit?
You can use the button, but I guess that isn't link-like so you don't want it, the following code shows how to use editor clickback to create a link-like text.
(require net/sendurl)
(define f (new frame% [parent #f]
[label "test"]
[width 300]
[height 300]))
(define editor (new text%))
(new editor-canvas% [parent f]
[editor editor])
(define t "https://www.google.com")
(send editor insert t)
(send editor set-clickback 0 (string-length t)
(λ (text start end)
(send-url t)))
(send* f
[show #t]
[center])

Text not centering on message% in Racket

I have following simple GUI code:
#lang racket/gui
(define myfr (new frame% [label ""] [width 200] [height 100]))
(define mymsg (new message% [label "See text position here."][parent myfr]))
(define mytf (new text-field% [label "Enter some text here."][parent myfr]))
(define bt (new button% [parent myfr] [label "Reset text"]
[callback (lambda (b e)
(send mymsg set-label
(send mytf get-value)))]))
(send myfr show #t)
Initially, the text position on message% is well centralized. However, when I change the text, it is no more well-centered. Why is this happening and how can this be corrected so that the new text is also well centered?
Add [auto-resize #t] to your message:
(define mymsg (new message% [label "See text position here."] [parent myfr] [auto-resize #t]))

Why text in text% not getting deleted?

I want to delete existing text from a text-area and insert new text but it is not working. I have following code:
#lang racket/gui
(define myframe (new frame%
[label "testing"]
[width 600]
[height 400]))
(define mytextarea (new text% ))
(new editor-canvas%
[parent myframe]
[editor mytextarea])
(define (button_fn button event)
(begin
(send mytextarea delete ; does not work;
(send mytextarea get-start-position)
(send mytextarea get-end-position))
(send mytextarea insert "New string inserted" 0) ; works;
))
(define mybutton (new button% [parent myframe]
[label "delete"]
[callback button_fn ]))
(send myframe show #t)
There is no error message. Where is the problem and how can it be solved?
The get-start-position and get-end-position return the start and end of the current selection; if there's no selection, then they both return the position of the cursor.
If you want to delete the whole contents of the text area, use last-position:
(send mytextarea delete 0 (send mytextarea last-position))
or you could use the erase method:
(send mytextarea erase) ;; deletes everything

how to align racket GUI text fields and buttons

I am creating a GUI for a racket program where a user inputs a title and a blog and then submits it. This is my code for those fields so far:
(define blogPost%
(class horizontal-panel%
(super-new)
(define titleoutput (new text-field% (label " title")
(min-height 20)
(min-width 200)
(vert-margin 20)
(horiz-margin 10)
(parent this)))
(define output (new text-field% (label "blog")
(style '(multiple))
(min-height 20)
(vert-margin 20)
(min-width 400)
(parent this)))
(define (callback button event)
(define title-new-value (send titleoutput get-value))
(define new-value (send output get-value))
(save title-new-value new-value)
(send output set-value "")
(send titleoutput set-value "")
(send howisit show #t))
(define button (new button% (label "Submit")
(vert-margin 0)
(horiz-margin 10)
(parent this)
(callback callback)))
))
It is currently aligned like this:
But I would like the title text box to be above the blog field and the submit button to be centered at the bottom.
I'm assuming that you're running this code in the same way as for your previous question. In that, you used your class like this:
(define f (new frame% [label "blog post GUI"] [min-width 400] [min-height 500]))
(define tib (new blogPost%
[parent f]))
(send f show #t)
Now since you defined blogPost% as a subclass of horizontal-panel%, it also inherits all of the initialization arguments of horizontal-panel%, including the alignment argument. So you can pass the [alignment '(left top)] initialization argument to your blogPost% class:
(define f (new frame% [label "blog post GUI"] [min-width 400] [min-height 500]))
(define tib (new blogPost%
[parent f]
[alignment '(left top)]))
(send f show #t)
If you want to build this default into your blogPost% class, you could add it to the (super-new) form instead:
(define blogPost%
(class horizontal-panel%
(super-new [alignment '(left top)])
...))
However, if you happen to have a (new blogPost% ... [alignment '(left top)] ...) around somewhere else, I believe this will break that code.
So to avoid that, it would probably be best to make the blogPost% class it's own class, so that instead of being a horizontal-panel%, it would have a horizontal-panel%, in the same way that it already has two text-fields and a button.
This is better for the long term because after this change, code that uses blogPost% won't break if you change which initialization arguments you passed to horizontal-panel% (which was implicit in the super-new previously).
(define blogPost%
(class object% ; object% instead of horizontal-panel%
; This argument is explicit now.
; If other code relies on other arguments, specify them here.
(init parent)
(super-new)
(define panel
(new horizontal-panel% ; this new call is explicit now
[parent parent] ; you can later add more arguments
[alignment '(left top)])) ; and it won't break things
(define titleoutput
(new text-field%
[label " title"]
[min-height 20]
[min-width 200]
[vert-margin 20]
[horiz-margin 10]
[parent panel])) ; panel instead of this
(define output
(new text-field%
[label "blog"]
[style '(multiple)]
[min-height 20]
[vert-margin 20]
[min-width 400]
[parent panel])) ; panel instead of this
(define (callback button event)
(define title-new-value (send titleoutput get-value))
(define new-value (send output get-value))
(save title-new-value new-value)
(send output set-value "")
(send titleoutput set-value "")
(send howisit show #t))
(define button
(new button%
[label "Submit"]
[vert-margin 0]
[horiz-margin 10]
[parent panel] ; panel instead of this
[callback callback]))
))
(define f (new frame% [label "blog post GUI"] [min-width 400] [min-height 500]))
(define tib (new blogPost%
[parent f]))
(send f show #t)
Of course, with this method, you won't be able to use the methods defined for horizontal-panel% on instances of your blogPost% class, but in the long run that's a good thing as well. If you ever, in the future, wanted to change the implementation to use something other than a horizontal-panel%, you could.

Run Code after Button Click using the racket/gui library

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". 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:
Thanks in Advanced,
Puzzledplane
GUI:
#lang racket
(require racket/gui/base)
;; 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 (new message% [parent maingroup]
[label "Insert Conditions Here from API"] ))
;; 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)
(let ([v (send zipInput get-value)])
(send zipcodelabel set-label v)
))]))
;; Show Frame
(send mainframe show #t)
XML Parsing:
#lang racket
(require net/url xml xml/path)
(define curent-cond-url (string->url "http://api.wunderground.com/api/*snip*/conditions/q/autoip.xml"))
(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))
(define current-conditions
(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)))

Resources