Modal Dialog Boxes

A modal dialog box requires the user to respond to it before changing the focus to other windows within the application. The Tk command tk_dialog is designed for this purpose, and can be called in R TclTk, using the tkdialog function. However, the method illustrated below will use the tktoplevel function and call tkgrab.set and tkgrab.release explicitly, rather than relying on tkdialog to call them automatically.

Modal Dialog Box Example

The following example defines a subroutine which creates a simple modal dialog box using tktoplevel to create the dialog window, and using tkgrab.set and tkgrab.release to force the user to respond to this dialog before changing focus to other window(s) in the applciation.

modalDialog <- function(title,question,entryInit,entryWidth=20,returnValOnCancel="ID_CANCEL")
{
  dlg <- tktoplevel()
  tkwm.deiconify(dlg)
  tkgrab.set(dlg)
  tkfocus(dlg)
  tkwm.title(dlg,title)
  textEntryVarTcl <- tclVar(paste(entryInit))
  textEntryWidget <- tkentry(dlg,width=paste(entryWidth),textvariable=textEntryVarTcl)
  tkgrid(tklabel(dlg,text="       "))
  tkgrid(tklabel(dlg,text=question),textEntryWidget)
  tkgrid(tklabel(dlg,text="       "))
  ReturnVal <- returnValOnCancel
  onOK <- function()
  {
    ReturnVal <<- tclvalue(textEntryVarTcl)
    tkgrab.release(dlg)
    tkdestroy(dlg)
    tkfocus(ttMain)
  }
  onCancel <- function()
  {
    ReturnVal <<- returnValOnCancel
    tkgrab.release(dlg)
    tkdestroy(dlg)
    tkfocus(ttMain)
  }
  OK.but     <-tkbutton(dlg,text="   OK   ",command=onOK)
  Cancel.but <-tkbutton(dlg,text=" Cancel ",command=onCancel)
  tkgrid(OK.but,Cancel.but)
  tkgrid(tklabel(dlg,text="    "))

  tkfocus(dlg)
  tkbind(dlg, "<Destroy>", function() {tkgrab.release(dlg);tkfocus(ttMain)})
  tkbind(textEntryWidget, "<Return>", onOK)
  tkwait.window(dlg)

  return(ReturnVal)

}

# Create a "main" window with a button which activates our dialog.
require(tcltk)
ttMain <- tktoplevel()
tkwm.title(ttMain,"ttMain")
launchDialog <- function()
{
  ReturnVal <- modalDialog("First Name Entry","Enter Your First Name","")
  if (ReturnVal=="ID_CANCEL")
    return()
  tkmessageBox(title="Greeting",message=paste("Hello, ",ReturnVal,".",sep=""))
}
launchDlg.button <- tkbutton(ttMain,text="Launch Dialog",command=launchDialog)
tkpack(launchDlg.button)

Clicking on the "Launch Dialog" gives a modal dialog box, i.e. you must respond to it before you can change the focus back to the main window in the Tk application.

Clicking "OK" gives the following message box: