TkLua: Accessing Tk Widgets

Almost all Tk widgets can be created based on the description provided by "TkLua: Basic Concepts". This page describes a few TkLua features that is not directly mapped to Tk resources. For a full describition on available widgets, see the Tk reference manuals.

Checkbutton and radiobutton widgets

Similar to entry widgets, checkbutton and radiobutton also have a current value associated, and it can be set or accessed using the current attribute.

The user can instantiate checkbutton widgets as in:

bold = tkcheckbutton{"Bold"; current = 1}
italic = tkcheckbutton{"Italic; current = 0}

This code creates two checkbuttons: one initially turned on (current=1) and another turned off (current=0, default). At any time, we can access the current value through the current attribute.

Instatiating radiobuttons is also simple. First we define a radiobutton to be the master. Subsequent radiobuttons that must work synchronizely has the first one as their master. Each radiobutton also has to have an associated value, thus the current value of the master radiobutton reports the active radiobutton.

gender = tkradiobutton{"Female"; value=0}
gender1 = tkradiobutton{"Male"; master=gender, value=1}

In the example above, if master.current has value 0, it means the female radiobutton is turned on, otherwise it will have value 1, meaning male is turned on. The value attribute can be avoided. In that case, it is assumed the radiobutton texts ("Female" and "Male" in the example above) to be the values.

Using listboxes and scrollbars

In general, scrollbars work attached to another widget. The widget where we attach a scrollbar has to support scrolling. The code below exemplify an instantiation of a listbox and a scrollbar working together.

color = tklistbox{"red","green","blue","yellow","magenta","black";
                  relief="raised",
                  borderwidth=2,
                  yscrollcommand="control:set(arg)"
                 }
control= tkscrollbar{command="color:yview(arg)"}

We can avoid the use of global variables:

 local color = tklistbox{"red","green","blue","yellow","magenta","black";
                         relief="raised",
                         borderwidth=2,
                         yscrollcommand="self.scroll:set(arg)"
                        }
 local control= tkscrollbar{command="self.list:yview(arg)"}
 
 -- after creating the objects, we cross-reference them
 color.scroll = control
 control.list = color

Do not forget that we can create an empty list and then use the method insert to add items to it.

Building menus

To create a menu using TkLua is something different from using Tcl/Tk. The reason is that we have included a new widget, what is the menuentry widget. Thus we first create a set of menuentries and then group them to form a menu. One menu can then be associated to a cascade menuentry or to a menubutton. Several menubuttons can be grouped into a frame, which can be assigned as the menu bar of a dialog, if desired.

Menuentry can be of several types:

The following code exemplifies how to build a dialog with a menubar:

i01 = tkmenuentry{"Red"; type="radiobutton"}
i02 = tkmenuentry{"Green"; type="radiobutton", master=i01}
i03 = tkmenuentry{"Blue"; type="radiobutton", master=i01}
m0 = tkmenu{i01,i02,i03; tearoff=0}

i1 = tkmenuentry{"Bold"; type="checkbutton"}
i2 = tkmenuentry{"Italic"; type="checkbutton"}
i3 = tkmenuentry{"Underline"; type="checkbutton"}
i4 = tkmenuentry{type="separator"}
i5 = tkmenuentry{"Times"; type="radiobutton"}
i6 = tkmenuentry{"Helvetica"; type="radiobutton", master=i5}
i7 = tkmenuentry{"Courier"; type="radiobutton", master=i5}
i8 = tkmenuentry{type="separator"}
i9 = tkmenuentry{"Insert Bullets"; type="command", command= "print('testing')" }
i10 = tkmenuentry{"Colors"; type="cascade", menu=m0}
m1 = tkmenu{i1,i2,i3,i4,i5,i6,i7,i8,i9,i10; tearoff = 1}

mb1 = tkmenubutton{"File"; underline=0}
mb2 = tkmenubutton{"Edit"; underline=0}
mb3 = tkmenubutton{"Graphics"; underline=0}
mb4 = tkmenubutton{"Text"; menu=m1, underline=0}
mb5 = tkmenubutton{"View"; underline=0}
mb6 = tkmenubutton{"Help"; underline=0}

f1 = tkframe{mb1,mb2,mb3,mb4,mb5,mb6; side="left", relief="raised", bd=2}

d = tkmain{f1; fill = "x"}
f1:menubar()
f1:focus()

d:show()

Menus can also be posted as pop-up menus. To do so, we create a menu and use its popup method. The popup method receives three parameter: the first specify the widget within which the pop-up menu will be posted; the second and the third parameters specify the position (in pixels, relative to the widget coordinates) to post the menu. As an example, considering we'd like to post a pop-up menu at cursor position within a canvas. We associate the pop-up method with the Button-1 event (see Binding events below). So each time the user presses the mouse left button, the menu will be poped up.

m = tkmenu{...}          -- create a menu with its menuentries
c = tkcanvas{...}        -- create a canvas
c:bind("<Button-1>","m:popup(c,arg.x,arg.y)    -- associate popup menu with button press

Menus are also used to implement drop-down list, named option menu in Tk. Given a menubutton, and its associated menu, we can create a option menu invoking the menubutton option method. This method accepts a parameter that specifies which menuentry is to considered active. If not specified, it is assumed the first menuentry.

m = tkmenu{...}           -- create a menu with its menuentries (representing options)
mb = tkmenubutton{menu=m} -- create a menubutton with the corresponding menu
mb:option(2)            -- convert to an option menu, with the second menuentry as active

Binding events

The general form to bind an event is:

object:bind (type, command)

Object can be of three different types:

Type follows Tk convention to specify which event is being bound. Command represents the action to be executed. Remenber that inside the command string we can access the object being bounded using self. It is also available the arg table. Here, the arg table stores the event fields. Thus:

Some valid bindings are:

tkWidget:bind("<Control-d>", "print('Control-d pressed')")
tkCanvas:bind("<Button1>", "print(arg.x, arg.y)")
object:bind("<Enter>", "print('cursor entered a specific object')")

Utility functions and window manager protocols

There is a set of utility function that can be called from Lua code:

Window manager protocols are set using the method protocol available on main and toplevel widgets. The general form to specify a window manager protocol is:

wn:protocol(protocol, command)

As an example, we could write:

wn:protocol("WM_DELETE_WINDOW", 'print("Exiting!") tkexit()')

Building modal dialog

As a more complete example, the code below implements a function that shows a modal dialog on the screen with the specified message.

function modal_message (title,text)

 local m = tkmessage{text;           -- create message
                     width='3i',
                     font='-Adobe-Times-Medium-R-Normal-*-180-*'
                    }
 
 local ok = tkbutton{"ok";           -- create 'ok' button
                     command="self.dialog:destroy()"
                    }

 local t = tktoplevel{m,ok}          -- create toplevel
 t:title(title)                      -- set title

 ok.dialog = t     -- store toplevel in button structure: used by the command

 -- bind <Return> key
 t:bind("<Return>", "self:destroy()")

 -- do interaction
 t:show()
 t:focus()
 t:grab()
 t:tkwait()
end

Command object

Tk provides a few procedures that pops up pre-defined dialogs. In TkLua, these procedures are bound to command objects. If a such object is created, the dialog is popped up, and the corresponding values are returned. There are four command objects available in TkLua: message box, dialog, choose color, open file, and save file.

To create a message box, we do:

tkmessagebox{title = title,
             message = message,
             icon = icon,
             type = type,
             default = default
            }

Valid shortcuts are:

tkmessagebox(message)
tkmessagebox(title,message)
tkmessagebox(title,message,type)

To create a dialog, we do:

tkdialog{title = title,
         text = text,
         bitmap = bitmap,
         string = {string1,string2,...},
         default = default
        }

Valid shortcuts are:

tkdialog(text)
tkdialog(title,text)
tkdialog(tilte,text,string1,string2,...)

To create a choose color dialog, we do:

tkchoosecolor{title = title,
              initialcolor = initialcolor
             }

And valid shortcuts are:

tkchoosecolor(title)
tkchoosecolor(title,initialcolor)

To create a open or save file dialog, we do:

tksavefile{title = title, -- or tkopenfile
           initialdir = initialdir,
           initialfile = initialfile,   -- not meaning for 'tkopenfile'
           filetypes = {{name="Lua files", extensions={".lua"}},
                       
 {name="C files", extensions={".c"}}
                       }
          }

Again, valid shortcuts are:

tksavefile(title)
tksavefile(title,initialdir)
tksavefile(title,initialdir,initialfile)

Timers and Idle function

From Lua, we can manipulate timers using the function:

tktimer (milliseconds, callback, userdata)

which creates and returns a timer. Different from Tcl/Tk timer, once created, the TkLua timer callback is called every millisecond, until the timer is explicitly deleted:

tkdeletedimer (timer)

We set an idle function by calling:

tkidle (callback)

A previously set idle function is cancelled by specifying nil to the above function.


Topics


Last update: November 1998 by W. Celes.