GUI component interaction
Almost every application needs to communicate with the user in some way. Therefore, a substantial part of the code deals with the interaction of program logic with GUI components. Typically, the following is needed:
- put values into input fields under program control
- read and check input from the user
- pop up dialogs to query the user for further information
You are encouraged to solve this task according to the task description, using any language you may know.
The task: For a minimal "application", write a program that presents a form with three components to the user: A numeric input field ("Value") and two buttons ("increment" and "random").
The field is initialized to zero. The user may manually enter a new value into the field, or increment its value with the "increment" button. Entering a non-numeric value should be either impossible, or issue an error message.
Pressing the "random" button presents a confirmation dialog, and resets the field's value to a random value if the answer is "Yes".
(This task may be regarded as an extension of the task Simple windowed application).
Oz
Using Mozart's standard GUI library: <lang oz>declare
[QTk] = {Module.link ['x-oz://system/wp/QTk.ozf']}
proc {Main} MaxValue = 1000 NumberWidget GUI = lr( numberentry(init:1 min:0 max:MaxValue handle:NumberWidget) button(text:"Increase" action:proc {$} OldVal = {NumberWidget get($)} in {NumberWidget set(OldVal+1)} end) button(text:"Random" action:proc {$} if {Ask "Reset to random?"} then Rnd = {OS.rand} * MaxValue div {OS.randLimits _} in {NumberWidget set(Rnd)} end end) ) Window = {QTk.build GUI} in {Window show} end
fun {Ask Msg} Result Box = {QTk.build td(message(init:Msg) lr(button(text:"Yes" action:proc {$} Result=true {Box close} end) button(text:"No" action:proc {$} Result=false {Box close} end) ))} in {Box show} {Box wait} Result end
in
{Main}</lang>
PicoLisp
The standard PicoLisp GUI is HTTP based. Connect your browser to http://localhost:8080 after starting the following script. <lang PicoLisp>#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
(load "@ext.l" "@lib/http.l" "@lib/xhtml.l" "@lib/form.l")
(de start ()
(and (app) (zero *Number)) (action (html 0 "Increment" "lib.css" NIL (form NIL (gui '(+Var +NumField) '*Number 20 "Value") (gui '(+JS +Button) "increment" '(inc '*Number) ) (gui '(+Button) "random" '(ask "Reset to a random value?" (setq *Number (rand)) ) ) ) ) ) )
(server 8080 "@start") (wait)</lang>
Tcl
<lang tcl>package require Tk
- --- Our data Model! ---###
- A single variable will do just fine
set field 0
- --- Lay out the GUI components in our View ---###
- We use the Ttk widget set here; it looks much better on Windows and OSX
- First, a quick hack to make things look even nicer
place [ttk::frame .bg] -relwidth 1 -relheight 1
- A labelled frame containing an entry field constrained to use numbers
pack [ttk::labelframe .val -text "Value"] pack [ttk::entry .val.ue -textvariable field \ -validate key -invalidcommand bell \ -validatecommand {string is integer %P}]
- Now, a pair of buttons
pack [ttk::button .inc -text "increment" -command step] pack [ttk::button .rnd -text "random" -command random]
- --- Now we define the behaviors, the Controller ---###
- How to respond to a click on the "increment" button
proc step {} {
global field incr field
}
- How to respond to a click on the "random" button
proc random {} {
global field if {[tk_messageBox -type yesno -parent . \
-message "Reset to random?"] eq "yes"} { set field [expr {int(rand() * 5000)}]
}
}</lang>