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
Task
GUI component interaction
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

Library: Tk

<lang tcl>package require Tk

      1. --- Our data Model! ---###
  1. A single variable will do just fine

set field 0

      1. --- Lay out the GUI components in our View ---###
  1. We use the Ttk widget set here; it looks much better on Windows and OSX
  1. First, a quick hack to make things look even nicer

place [ttk::frame .bg] -relwidth 1 -relheight 1

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

  1. Now, a pair of buttons

pack [ttk::button .inc -text "increment" -command step] pack [ttk::button .rnd -text "random" -command random]

      1. --- Now we define the behaviors, the Controller ---###
  1. How to respond to a click on the "increment" button

proc step {} {

   global field
   incr field

}

  1. 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>