Non-resizable frame in Racket - scheme

I am trying to create a non-resizable frame to give a message:
#lang racket/gui
(define (non_resizable_frame)
(define myframe (new frame%
[label "MyFrame"]
[style (list 'no-resize-border)] ; does not work.
))
(new message% [parent myframe][label "This is just for testing."])
(new message% [parent myframe][label "I am trying to create a non-resizable frame."])
(send myframe show #t))
(non_resizable_frame)
However, the frame still is resizable. Where is the problem and how can I solve this?

Set the stretchable-width and stretchable-height init arguments to #f when constructing the frame.

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

How to add an Image on a Frame in the Racket GUI Toolkit?

How can one add an image (for example png) onto a frame% object?
#lang racket
(define my-frame (new frame%))
;want to add an image to my-frame
Use a canvas.
(define my-frame (new frame%
[label "Example"]
[width 300]
[height 300]))
(new canvas%
[parent my-frame]
[paint-callback
(λ (canvas dc)
(send dc draw-bitmap (read-bitmap "/path/to/image.png") 0 0))])
(send my-frame show #t)

GUI component layout in Racket/Scheme

I am using following code for a small GUI program:
#lang racket/gui
(define ff (new frame%
[label "Adjust widths"]
[height 100]
[width 300]))
(new message% [parent ff][label "testing"])
(new text-field% [parent ff][label "tf1"])
(new text-field% [parent ff][label "tf2- a long prompt"])
(new text-field% [parent ff][label "tf3 "])
(new text-field% [parent ff][label "tf4 "])
(send ff show #t)
However, I am not able to get desired layout:
How can I get above layout. I see text-field and other components have min-width and stretchable-width. Which if these is default and which is actual is not clear to me. How can I fix the width of text-field? Should I use table-panel package for this? Thanks for your help.
Edit: I checked https://docs.racket-lang.org/gui/windowing-overview.html?q=gui and also tried different options such as [min-width 50] and [stretchable width #f] but apparently it is not possible to fix the size of text-field to a particular value.
One possibility is to first set the labels to the one of maximum width, then change them to the desired label. This works for me at least.
#lang racket/gui
(define ff (new frame%
[label "Adjust widths"]
[height 100]
[width 300]))
(new message% [parent ff][label "testing"])
(define strings
'("tf1" "tf2- a long prompt" "tf3" "tf4"))
(define str-max (argmax string-length strings))
(define txt-fields
(for/list ([str (in-list strings)])
(new text-field% [parent ff] [label str-max])))
(for ([tf (in-list txt-fields)]
[str (in-list strings)])
(send tf set-label str))
(send ff show #t)
Since fonts may not have a fixed width, you may want to use underscores for the string of maximum length.
Another possibility is to get rid of the text-field's label altogether by passing #f as argument and make your own using a message% for which you can actually control the width with min-width. You may need to put the message and the text-field in a horizontal-panel%.

How to design a Button with an icon or pict in Racket?

I want to do Buttons and so to look nicer when doing windowing in Dr Racket. I did not found an example how to do it and where are icons stored.
Isabel
You can load a bitmap and use it as the label argument when making a new button%:
#lang racket/gui
(define frame (new frame% [label ""]))
(define button-icon (read-bitmap "path/to/image"))
(define button (new button% [label button-icon] [parent frame]))
(send frame show #t)

Racket GUI tab-panel dynamic content

I am looking into GUI development with Racket. I would like to create a tab-panel%, with multiple tabs. The documentation says, that a switch of tab does only call a procedure and does not make a content change happen automatically. I think this is quite clever behavior, but I have a problem implementing an initially empty tab-panel, which only gets content (children) when I select one of the tabs.
This is the code I already have:
#lang racket/gui
(require racket/gui/base)
(define nil '())
(define application-frame
(new frame%
[label "Example"]
[width 400]
[height 300]))
(define menu-bar
(new menu-bar%
[parent application-frame]))
(define file-menu
(new menu%
[label "&File"]
[parent menu-bar]))
(new menu%
[label "&Edit"]
[parent menu-bar])
(new menu%
[label "&Help"]
[parent menu-bar])
(new menu-item%
[label "E&xit"]
[parent file-menu]
[callback
(λ (m event)
(exit nil))])
(define tab-panel
(new tab-panel%
[parent application-frame]
[choices '("&Lookup" "&Training")]
[callback
(λ (tp event)
(case (send tp get-item-label (send tp get-selection))
[("&Lookup")
(send tp change-children
(λ (children)
(list lookup-panel)))]
[("&Training")
(send tp change-children
(λ (children)
(list training-panel)))]))]))
(define get-lookup-panel
(lambda (children)
(let
[(lookup-panel (new panel% [parent tab-panel]))]
[(new message%
[parent lookup-panel]
[label "The content of the lookup panel for the lookup tab."])
lookup-panel])))
(define lookup-panel (new panel% [parent tab-panel]))
(define lookup-panel-content
(new message%
[parent lookup-panel]
[label "The content of the lookup panel for the lookup tab."]))
(define training-panel (new panel% [parent tab-panel]))
(define training-panel-content
(new message%
[parent training-panel]
[label "The content of the training panel for the training tab."]))
(define status-message
(new message%
[parent application-frame]
[label "No events so far..."]
[auto-resize #t]))
(send application-frame show #t)
The problem here is, that initially both children of the tab-panel are visible, although (naturally) only one tab is selected. When I change tab, the behavior is corrected by the lambdas inside the case form.
However, I cannot simply give those panels, which I set as children no parent, because racket will tell me, that I need to specify the required initial argument parent. This means they will be initially added to the tab-panel. Is it necessary to create the panels and then again remove them from the tab-panel? That would seem a bit dirty. I think there is probably a better way.
I already tried to dynamically create the panel, as can be seen in the get-lookup-panel procedure, but I couldn't get that to work in the case form.
What is the correct way to implement it?
edit1
I found a way to define a procedure, which can be used in the way I want to use it:
(define (get-lookup-panel4 children)
(define lookup-panel (new panel% [parent tab-panel]))
(define lookup-panel-message (new message% [parent lookup-panel] [label "LOOKUP"]))
(list lookup-panel))
Which can be used as follows:
(define tab-panel
(new tab-panel%
[parent application-frame]
[choices '("&Lookup" "&Training")]
[callback
(λ (tp event)
(case (send tp get-item-label (send tp get-selection))
[("&Lookup")
(send tp change-children get-lookup-panel4)]
[("&Training")
(send tp change-children
(λ (children)
(list training-panel)))]))]))
But I don't understand what the difference between this procedure and the other one with the let expression is and another problem with this approach is, that I cannot afterwards modify the created panel or message, because their scope is the procedure.

Resources