How to make a GUI using Lisp: DrScheme or Common Lisp - user-interface

Or the basic work need to do to create a GUI. I know the basic Components
of GUI, but where to begin. I'm just a self-study person and I'm reading "How to Design Program" (HtDP) at the end of the book the author suggest that knowledge of GUI and CGI computer network are needed to be a programmer. The information of the last two is easy to find. But it seems there are little book talking about how to create a GUI. I guess maybe it's too "low" in the process designing the computer program that few people even care.

The documentation for GUI programming in DrRacket (the name of current versions of DrScheme) is here: http://docs.racket-lang.org/gui/index.html
Since you're reading HTDP, this is probably the best option for you right now.

If you want to just make the simple GUI in Common Lisp, your best
choice, in my opinion, is LTK, which is a high-level interface to
Tcl/Tk scripting library
There are plenty of other choices, but they require some
vision of what you are trying to achieve. If you want to use
one of the wide-spread GUI toolkits (GTK or Qt) there are CL-GTK2
and CommonQt. But you have to first of all understand well, how these
toolkits work
LispWorks provides a very sophisticated GUI-builder library CAPI,
which is cross-platform
On the Mac ClozureCL has good Cocoa bindings
Finally there's a full-blown native CL solution for GUI - McCLIM -
which is very flexible, but pretty involved
Also, if you want to understand GUI and study it from the theoretical point of view, you should learn about various GUI-patterns, such as MVC, Model2, MVVM etc. I don't know about any GUI-framework in Lisp, implementing such patterns, so doing such a project may be an interesting learning experience...

There's a lightweight library for writing simple graphical programs through 2htdp/universe. See: How to Design Worlds.
The basic idea is that modern graphical libraries are highly event-driven: you interact with the external world by responding to events. If you look at it closely enough, the universe library is an implementation of the MVC model: the world is the "Model", the to-draw the "View", and all the other event handlers the "Controller".
If you want to work with more low-level elements in Racket, you can use the racket/gui libraries. These have reference documentation in The Racket Graphical Interface Toolkit. Here's a small example that uses the library:
#lang racket
(require racket/gui/base
2htdp/image
(only-in mrlib/image-core render-image))
;; The state of our program is a number.
(define state 0)
;; On a timer tick, increment the state, and refresh the canvas.
;; tick!: -> void
(define (tick!)
(set! state (add1 state))
(send THE-CANVAS refresh))
;; When a canvas paints itself, use the following:
;; paint: canvas% dc<%> -> void
(define (paint! a-canvas my-drawing-context)
(define my-new-scene (text (format "I see: ~a" state) 20 'black))
;; Note: we force the canvas to be of a particular width and height here:
(send a-canvas min-client-width (image-width my-new-scene))
(send a-canvas min-client-height (image-height my-new-scene))
(render-image my-new-scene my-drawing-context 0 0))
;; Here, we initialize our graphical application. We create a window frame...
;; THE-FRAME: frame%
(define THE-FRAME (new (class frame%
(super-new)
;; When we close the frame, shut down everything.
(define/augment (on-close)
(custodian-shutdown-all (current-custodian))))
[label "Example"]))
;; and add a canvas into it.
;; THE-CANVAS: canvas%
(define THE-CANVAS (new (class canvas%
(super-new)
;; We define a key handler. Let's have it so it
;; resets the counter on a key press
(define/override (on-char key-event)
(when (eq? (send key-event get-key-code) 'release)
(set! state 0)
(send THE-CANVAS refresh))))
[parent THE-FRAME]
[paint-callback paint!]))
;; We get the frame to show on screen:
(send THE-FRAME show #t)
;; Finally, we set up a timer that will call tick! on every second.
(define THE-TIMER (new timer%
[notify-callback tick!]
[interval 1000]))

A recent article on the current state of the Common Lisp ecosystem says: CommonQt plus Qtools is the way to go nowadays.

Related

Text box that only accepts numbers in Racket's GUI library

In Racket's GUI library, I can use a text-field% to add a single line textbox to a window. However, I would like to limit this text box to only allow integers to be typed.
One possible way to handle this is to insert a callback whenever a letter is typed, to add it into the text box ourselves. The text-field% class has methods get-value and set-value, but there are only used for programmatic modification of the text box, and not as a callback.
Another way would be to pass in a regex for allowable characters or strings in the text box, but this does not seem to be supported either.
So, is there any way to create a text field in Racket that will only allow the user to type in integers?
It would appear that there already is a solution to this problem on Rosetta Code. What you 'can' do in a text box is set a callback that is called whenever the user types. Then, you can use set-value to remove the character that you didn't want there. The resulting text-field% object would look like this (taking it from the link):
(new text-field% [label "Value"] [parent frame] [init-value "0"]
[callback
(λ (f ev)
(define v (send f get-value))
(unless (string->number v)
(send f set-value (regexp-replace* #rx"[^0-9]+" v ""))))]))
Where frame is the frame you are putting in the text box, say:
(define frame (new frame% [label "Demo Frame"))

How to exit from a GUI application without frame's [x] button in Racket

Is 'exit' the proper way to exit a gui application in Racket using a button or is some other method best for this?
(define myfr
(new frame% [label "myframe"] [width 100] [height 100] ))
(new message% [label "my gui app"][parent myfr])
(define exitbutton
(new button% [parent myfr] [label "Exit"]
[callback (lambda (b e) (exit) )]))
(send myfr show #t)
I find that DrRacket gives "Interactions disabled" warning message on using the exit button but there is a clean exit when closing using frame's [x] button.
I found "on-exit" method but not actual exit method on this page: https://docs.racket-lang.org/gui/frame_.html?q=frame%25 . Also nothing specific is mentioned on https://docs.racket-lang.org/reference/Exiting.html
Following statement, I believe, will only hide the frame and not close the application:
(send myfr show #f)
The exit is absolutely the way you want to end an application. The reason why the REPL in DrRacket stops when you do it, however, is because your program is no longer running, which will happen whenever you call exit, even if there is no gui in your program.
You are also correct that:
(send myfr show #f)
will hide the window but not actually quit the app.
So, one thing you could do is try to test if you are running in DrRacket or not. And if you are, rather than exiting the program, just close the window, and let DrRacket quit the application after the user clicks kill or starts a new program.
The problem with this is that in general, it is not possible to detect if you are running in a sandbox. There are some hacks you can do to test this out, but it's not very robust:
Determin if a racket program is in a sandbox
Another approach would be to create your own sandbox, and run your program in that sandbox (which is how DrRacket will run your code actually). Then, when your program exits, there will still be an available repl. Although be aware that the repl will be for the sandbox itself, rather than the repl it is in.
Here is the documentation for creating a sandbox.
Leif already explained it fully, but I just wanted to describe it differently to a more novice audience.
"gui application" you refer in your question may mean different things depending on where you're running that code piece.
If run from DrRacket REPL, the lambda (exit) will exit from the REPL (leading to "interactions disabled" message). If this code is a piece of a script run by racket executable (for example, from the command line), it will exit that script / shell (probably what you want).
I'm not sure if you want to try in the exit code understanding if you're in a sandbox or REPL and behave differently on exit button click per environment, but again Leif also pointed to an answer for it, too.
Another reason for writing this somehow unnecessary addition to Leif's answer is, I wanted to point to your term "gui application". My apologies if I'm sounding patronizing. Showing a gui frame or other graphical interfaces in your application is a functionality that you choose to use, and doesn't make the application something different. One difference from an Operating System's perspective would be a callback function associated with a top-level frame/window. And that callback function is nicely (most probably - although I didn't examine details of racket's code for it) registered and handled by the language in our case. So I'd like to say - showing a gui or not I would consider them the same, and it will exit when you call (exit). And normally (probably) the x button of a frame will hide it by default (as you're already aware, hence you added the exit lambda function). You application can unhide it during the application lifetime.

How to make the cursor always jump to point-max for Emacs gdb?

When debugging in Emacs with gdb-mi, the cursor in *gud-xxx* window always fails to jump to point-max, then I follow some other's settings and make some advice like below:
(defun hack-gud-mode ()
(when (string= major-mode "gud-mode")
(goto-char (point-max))))
(defadvice switch-to-buffer (after switch-to-buffer-after activate)
(hack-gud-mode))
(defadvice comint-send-input (after comint-send-input-after activate)
(hack-gud-mode))
(defadvice windmove-do-window-select (after windmove-do-window-select-after activate)
(hack-gud-mode))
(defadvice gud-call (after gud-call-select-after activate)
(hack-gud-mode))
But the problem still exists: when I hit some gdb command and press Ret(comint-send-input), there is still no guarantee that the cursor would jump. Also I feel that it is too frustrating to add so many advice functions. Is there any better setting for it?
(Strictly for the sake of completion, I'm writing here what #assem proposed in the comments.)
comint-scroll-to-bottom-on-input scrolls the comint buffer whenever you enter stuff.
comint-scroll-to-bottom-on-output scrolls the buffer along with the output (this is probably the most relevant one).
You should set them both to t using:
(setq comint-scroll-to-bottom-on-input t)
(setq comint-scroll-to-bottom-on-output t)
You may also want to set comint-scroll-to-bottom-on-output to 'others instead of t. This way it will only scroll if the buffer is not currently focused.
I cannot be 100% sure (since my gdb works fine), but I would experiment by changing your hack-gud-mode by adding something like
(run-with-timer 0.25 nil (lambda () (goto-char (point-max))))
Since there is a small delay between emacs sending stuff to underlying process and emacs getting the response. Only the comint-send-input would need to be adviced, if this works
(however, I wonder about the root cause of your problem)

Compatibility issue with drRacket: "require" and "frame"

I wonder if my drRacket has a problem :
I see example on the internet of programs but when I put them in Dr racket, it considers them as an error.
It first append when I write (require racket/base) at the begining of a new file. It immediately consider it like an error. So I replace it with #lang racket/base and it was ok but it is strange, I still don't know why it doesn't work.
Then, I try to use this command : (define FRAME (new frame% [label "Graphic"] [width 500] [height 500]))
but it show me a new error : new: unbound identifier in module in: new.
This time I am unable to find something that work to show me my graphic :(
I dont't get it : why when I copy-past program that work on the net, they don't whant to whork whith me? It is really frustrating. I download the last version of the programme (version 5.3.3) and it does not solve my problem.
Anybody can explain it work with other person but it don't work with me? Or maybe tell me how to do my graphic?
First I'd suggest you start every program with just
#lang racket
since this gives you the full base of the Racket language. Also make sure DrRacket is set to "determine language from source" (bottom left on Mac OS X).
Nevertheless some things need to be imported. If you look up new in the docs, for example, it is provided by racket/class or racket, not by racket/base, which explains the message you get.
frame% is provided by racket/gui or racket/gui/base, so finally this will work:
#lang racket
(require racket/gui)
(define FRAME (new frame% [label "Graphic"] [width 500] [height 500]))
The example you copy-pasted probably included the require statement.
Try to get comfortable with reading the Racket docs, they are well written and searchable.

How do you compile an executable file in scheme?

I want to make an executable file for the following code.
This is scheme written in Dr.racket.
How would this be done?
It would be best if it can be stand-alone and if I can open it in on iOS and Windows.
Thank you very much for your time!
#lang racket
(require racket/gui/base)
(require compiler/embed)
; Make a frame by instantiating the frame% class
(define frame (new frame% [label "GUI"]
[width 200]
[height 200]))
; Make a static text message in the frame
(define msg (new message% [parent frame]
[label "This box is empty"]))
; Show the frame by calling its show method
(send frame show #t)
As pointed by #dyoo, in Racket you can create an executable from the menu and (depending on the selected/available options) pack the required libraries; read the instructions. Also you can create executables for other platforms using command line tools.
For a more general and portable solution, consider compiling the code to C first and then compile from C to a native executable; take a look at the raco tool (section 9.3), or look at a Scheme implementation designed for easily compiling to C, such as Chicken Scheme or Gambit Scheme.
Getting the code to run under iOS might be trickier, a quick search returned a Gambit REPL for iOS, give it a try but I don't think there's support for compiling to native Objective-C code, although Gambit claims to have "full integration support for C++ and Objective-C compilers", you'll have to experiment with it a bit.
Finally, notice that GUI code specific to Racket (like the one in the question) will almost certainly be non-portable across different Scheme implementations/platforms...

Resources