C++/Tk library

http://cpptk.sourceforge.net/

version 1.0.2

Introduction
Commands
Additional Tcl commands
Widget commands
Options
Constants
Loose bits and pieces
Compiling

Introduction

The C++/Tk library does not need any extensive documentation, since it is meant to provide interface to the existing GUI toolkit.
If you already know Tk from elsewhere (for example, from Tcl), you will find C++/Tk very intuitive.
If not, you may find tons of Tk-related tutorials on the web and you may also buy good books about this toolkit. Those that I know and can recommend are:

Of course, it was necessary to change the original syntax in order to make it parseable by the C++ compiler. In some particular cases, it was necessary to change the names of commands and options, to resolve conflicts. The rest of this document presents the examples for each Tk element, listed alphabetically.

In the following examples, names ".b1", ".b2", etc. denote existing buttons, ".f1", ".f2", etc. denote existing frames, etc.


Commands

Tk command C++/Tk example
bell bell();
bind void fun1();
void fun2(int x, int y);
void fun3(string const &win, int x, int y);
// and later:
bind(".f1", "<Button-1>", fun1);
bind(".f2", "<Button-1>", fun2, event_x, event_y);
bind(".f3", "<Button-1>", fun3, event_W, event_x, event_y);

Note: You can specify arguments (up to 10) to the callback functions (like % substitutions in Tcl/Tk) with the help of event_ specifiers, but the number of function parameters and their types should match the given specifiers, otherwise the code will not compile.

bindtags bindtags(".b1");
bindtags(".b1", "all . Button .b1");
button button(".b1") -text("Press me") -command(fun);
string bname(button(".b2") -text("Press me too") -fg("blue") -command(fun));
canvas canvas(".c");
checkbutton checkbutton(".cb") -text("select me");
clipboard clipboard(clear);
clipboard(clear) -displayof(".top");
clipboard(append, "hello");
string s(clipboard(get));
console - (not implemented)
destroy destroy(".b");
entry entry(".e");
event - (not implemented)
focus focus() -displayof(".");
focus(".e");
focus() -force(".e");
focus() -lastfor(".");
font fonts(create, "myfont");
fonts(configure, "myfont") -size(20) -underline(true);
fonts(deletefont, "myfont");
fonts(families);

The actual, measure and metric options are not implemented.

frame frame(".f");
grab string cur(grab(current));
string cur(grab(current, ".f"));
grab(release, ".f");
grab(set, ".f");
grab(setglobal, ".f");
string stat(grab(status, ".f"));
grid Box b(grid(bbox, ".", 2, 3));
grid(columnconfigure, ".", 3) -minsize(5) -weight(2) -uniform("abc") -pad(5);
grid(configure, ".b") -column(3) -columnspan(2) -in(".") -row(2) -rowspan(2) -sticky("nw");
grid(forget, ".e");
image string img(images(create, bitmap));
images(create, photo, "myimg") -file("myimg.jpg");
images(deleteimg, "myimg");
int h(images(height, "myimg"));

Note: bitmap options -data and -maskdata are not implemented (use -file and -maskfile instead).

Note: photo options -data and -format are not implemented.

label label(".lab");
labelframe labelframe(".lf");
listbox listbox(".lb");
lower lower(".e");lower(".e", ".f");
menu menu(".m");
menubutton menubutton(".mb");
message message(".msg");
option option(add, "abc", "def");
option(add, "abc", "def", interactive);
option(clear);
option(get, ".w", "abc", "def");
option(readfile, "file");
pack pack(".b") -side(left) -expand(true) -fill(x);
pack(configure, ".b") -padx(5);
pack(".b1", ".b2", ".b3");
panedwindow panedwindow(".pw");
place place(".b") -relx(5) -rely(10);
place(configure, ".b") -relx(5);
radiobutton radiobutton(".rb");
raise raise(".b");
raise(".b", ".f");
scale scale(".s");
scrollbar scrollbar(".sb");
selection selection(clear) -displayof(".w") -sel("PRIMARY");
selection(get) -cliptype("STRING");

Note: selection handle and selection own commands are not implemented.

send - (not implemented)
spinbox spinbox(".sp");
text textw(".t");
tk - (not implemented)
tk_chooseColor string newColor(tk_chooseColor() -initialcolor("blue") -parent(".") -title("select color"));
tk_chooseDirectory string newDir(tk_chooseDirectory() -initialdir("/usr/home") -mustexist(true));
tk_dialog string response(tk_dialog(".d", "some title", "some text", warning, "OK", "OK", "Cancel"));
tk_focusNext
tk_focusPrev
tk_focusNext(".b");
tk_focusPrev(".b");
tk_focusFollowsMouse - (not implemented)
tk_getOpenFile
tk_getSaveFile
string newFile(tk_getOpenFile() -defaultextension(".txt") -filetypes("{{Text files} {.txt}}") -initialfile("file.txt") -multiple());
tk_menuSetFocus tk_menuSetFocus(".m");
tk_messageBox tk_messageBox() -defaultbutton("ok") -icon(question) -messagetext("some text") -messagetype(okcancel);
tk_optionMenu string menuVal;
tk_optionMenu(".m", menuVal, values.begin(), values.end());
tk_setPalette tk_setPalette("blue");
tk_textCopy
tk_textCut
tk_textPaste
tk_textCopy(".t");
tk_textCut(".t");
tk_textPaste(".t");
tk_error - (not implemented)
tkvars - (not implemented)
tkwait tkwait(visibility, ".w");
tkwait(window, ".w");
toplevel toplevel(".w");
winfo winfo(rootx, ".w");
wm wm(geometry, ".w", "=100x200+50+60");
wm(iconify, ".w");
wmprotocol(".w", "WM_DELETE_WINDOW", fun);

Additional Tcl commands

Tcl command C++/Tk example
after after(500);
after(500, fun);
afteridle(fun);
update update();
update(idletasks);

Widget commands

Tk widget command C++/Tk example
activate ".lb" << activate(5);
add ".m" << add(command) -label("choose me") -command(fun);
addtag string myrectangle(".c" << create(rectangle, 10, 20, 30, 40));
".c" << addtag("mytag", myrectangle);
".c" << addtag("mytag2", enclosed, 0, 0, 100, 100);
bbox Box b1(".c" << bbox("mytag"));
vector<string> items;
// ...
Box b2(".c" << bbox(items.begin(), items.end())); // any InputIterator allowed
".e" << bbox(5);
bind ".c" << bind(...); // see also the command bind above
blank "myphoto" << blank();
canvasx
canvasy
int x1 = (".c" << canvasx(57));
int x2 = (".c" << canvasx(57, 10));
cget string color(".b1" << cget(foreground));
int w = (".b1" << cget(width));
compare ".t" << compare(txt(5,6), "<", txt(6,5));
configure ".b1" << configure() -foreground("blue");
".b2" << configure() -state(disabled);
coords Box b(".c" << coords(myrectangle));
".c" << coords(mytext, 100, 50);
".c" << coords(Point(100, 50));
".c" << coords(myrectangle, 10, 20, 30, 40);
".c" << coords(myrectangle, Point(10, 20), Point(30, 40));
".c" << coords(myrectangle, Box(10, 20, 30, 40));
int crds[] = {10, 20, 30, 40, 50, 60, 70, 80};
".c" << coords(mypolygon, &crds[0], &crds[0] + 8); // any InputIterator allowed
create ".c" << create(text, 100, 50) -text("Hello");
".c" << create(text, Point(100, 50));
".c" << create(rectangle, 10, 20, 30, 40);
".c" << create(rectangle, Point(10, 20), Point(30, 40));
".c" << create(rectangle, Box(10, 20, 30, 40));
int crds[] = {10, 20, 30, 40, 50, 60, 70, 80};
".c" << create(line, &crds[0], &crds[0] + 8); // any InputIterator allowed
curselection string cur(".lb" << curselection());
dchars ".c" << dchars(mytext, 4, 7);
debug ".t" << debug();
".t" << debug(true);
delete ".m" << deleteentry(5);
".m" << deleteentry(5, 8);
".c" << deleteitem(myrectangle);
vector<string> items;
// ...
".c" << deleteitem(items.begin(), items.end()); // any InputIterator allowed
".e" << deletetext(5);
".e" << deletetext(5, end);

Note1: deleteentry, deleteitem and deletetext with one argument are equivalent.

Note2: deleteentry and deletetext with two arguments are equivalent. Only deleteitem with two arguments accepts iterators.

delta ".sb" << delta(50, 60);
deselect ".cb" << deselect();
dlineinfo ".t" << dlineinfo(txt(5,6));
dtag ".c" << dtag(mytag);
".c" << dtag(mytag1, mytag2);
dump ".t" << dump(txt(5,6)) -all();
edit ".t" << edit(undo);
entrycget ".m" << entrycget(5, menulabel);
find string items(".c" << find(enclosed, 0, 0, 100, 100)); // args like with addtag
flash ".b1" << flash();
focus string focused(".c" << focus());
".c" << focus(mytext);
forget ".pw" << forget(".b");
fraction ".sb" << fraction(50, 60);
get ".e" << get();
".lb" << get(5);
".lb" << get(5, 8);
gettags string tags(".c" << gettags(myrectangle));
icursor ".c" << icursor(mytext, 5);
".c" << icursor(mytext, end);
".e" << icursor(5);
identify ".pw" << identify(50, 60);
image ".t" << images(cget, txt(5,6), align);
".t" << images(configure, txt(5,6)) -align(bottom);
index ".c" << index(mytext, end);
".e" << index(at(25));
insert ".c" << insert(mytext, end, "hello");
".e" << insert(5, "hello");
".m" << insert(5, checkbutton);
invoke ".b" << invoke();
".m" << invoke(5);
itemcget
itemconfigure
".c" << itemcget(myrectangle, outline);
".lb" << itemcget(5, background);
".c" << itemconfigure(myrectangle) -outline("blue");
".lb" << itemconfigure(5) -background("blue");
lower ".c" << lower(myrectangle);
".c" << lower(myrectangle, myoval);
mark ".t" << mark(set, "mymark", txt(5,6));
".t" << mark(gravity, "mymark", left);
move ".c" << move(myrectangle, 10, 20);
moveto ".sb" << moveto(0.2);
panecget
paneconfigure
".pw" << panecget(".b", height);
".pw" << paneconfigure(".b") -height(20);
panes ".pw" << panes();
post
postcascade
".m" << post(100, 150);
".m" << postcascade(5);
postscript ".c" << postscript() -colormode(color) -file("file.eps");
proxy ".pw" << proxy(place, 50, 60);
".pw" << proxy(forget);
put "photo1" << put("red") -to(10, 20);

Note: only single colors are supported.

raise ".c" << raise(myrectangle);
read "photo1" << read("photo.gif") -to(10, 20);
redither "photo1" << redither();
sash ".pw" << sash(place, 2, 50, 60);
scale ".c" << scale("item", 10, 20, 1.5, 1.6);
scan ".c" << scan(mark, 10, 20);
".e" << scan(mark, 10);
scroll ".sb" << scroll(5, units);
search ".t" << search("pattern", txt(5,6), txt(5,end));
see ".t" << see(txt(5,6));
select ".c" << select(clear);
".cb" << select();
selection ".e" << selection(from, 5);
".lb" << selection(set, 5, 8);
set ".s" << set(150);
".sb" << set(0.2, 0.4);
size int size(".lb" << getsize());
tag ".t" << tag(add, txt(5,6), txt(5,end));
".t" << tag(bind, "mytag", "<Button-1>", fun);
".t" << tag(cget, "mytag", background);
".t" << tag(deletetag, "mytag");
toggle ".cb" << toggle();
transparency "photo1" << transparency(get, 10, 20);
"photo1" << transparency(set, 10, 20, true);
type string mytype(".c" << type(myitem));
validate ".e" << validate();
window ".t" << windows(cget, txt(5,6), align);
".t" << windows(configure, txt(5,6)) -align(center);
".t" << windows(create, txt(5,6));
".t" << windows(names);
write "photo1" << write("photo.gif") -from(10, 20, 30, 40) -grayscale();
xview
yview
".c" << xview(moveto, 0.5);
".c" << yview(scroll, 5, units);
".e" << xview(5);
yposition int y = (".m" << yposition(5));

Options

Tk option C++/Tk example
accelerator ".m" << entryconfigure(5) -accelerator("Ctrl-x");
activebackground
activeborderwidth
activeforeground
activerelief
button(".b") -activebackground("blue");
menu(".m") -activeborderwidth(3);
button(".b") -activeforeground("blue");
scrollbar(".sb") -activerelief(sunken);
after pack(configure, ".b1") -after(".b2");
anchor pack(".b") -anchor(w);
aspect message(".msg") -text("hello world") -aspect(100);
autoseparators textw(".t") -undo(true) -autoseparators(true);
background
bg
button(".b") -background("white");
button(".b") -bg("white");
before pack(configure, ".b1") -before(".b2");
bgstipple ".t" << tag(configure, "mytag") -bgstipple("mybitmap");
bigincrement scale(".s") -bigincrement(10);
bitmap button(".b") -bitmap(warning);
bordermode place(".b") -bordermode(inside);
borderwidth
bd
frame(".f") -borderwidth(3);
frame(".f") -bd(3);
buttonbackground
buttoncursor
buttondownrelief
buttonuprelief
spinbox(".sp") -buttonbackground("blue") -buttoncursor("mycursor") -buttondownrelief(sunen) -buttonuprelief(raised);
class frame(".f") -wndclass("myclass");
closeenough canvas(".c") -closeenough(3.0);
colormap labelframe(".lf") -colormap("new");
columnbreak ".m" << add(radiobutton) -columnbreak(true);
command button(".b") -command(fun); // fun is any function or function object with no parameters
compound button(".b") -compound(left);
confine canvas(".c") -confine(true);
container labelframe(".lf") -container(true);
cursor frame(".f") -cursor(mycursor);
default button(".b") -defaultstate(active);
digits scale(".s") -digits(3);
direction menubutton(".mb") -direction(above);
disabledbackground
disabledforeground
entry(".e") -disabledbackground("gray");
button(".b") -disabledforeground("gray");
elementborderwidth scrollbar(".sb") -elementborderwidth(2);
elide ".t" << tag(configure, "mytag") -elide(true);
expand pack(".b") -expand(true);
exportselection ".e" << configure() -exportselection(true);
fill pack(".b") -expand(true) -fill(x);
font label(".l") -text("hello") -font("courier");
foreground
fg
button(".b") -foreground("blue");
button(".b") -fg("blue");
fgstipple ".t" << tag(configure, "mytag") -fgstipple("mybitmap");
format spinbox(".sp") -format("%0.2f");
from "photo1" << copy("photo2") -from(10, 20, 30, 40);
scale(".s") -from(1000);
gamma images(create, photo) -gamma(1.5);
grayscale "photo1" << write("photo.gif") -grayscale();
handlepad
handlesize
panedwindow(".pw") -handlepad(50) -handlesize(10);
height frame(".f") -height(100);
highlightbackground
highlightcolor
highlightthickness
button(".b") -highlightbackground("blue") -highlightcolor("blue") -highlightthickness(5);
image button(".b") -image(myimage);
in pack(".b") -in(".f");
increment spinbox(".sp") -from(0) -to(10) -increment(0.1);
indicatoron checkbutton(".cb") -indicatoron(false);
insertbackground
insertborderwidth
canvas(".c") -insertbackground("blue") -insertborderwidth(3);
insertofftime
insertontime
insertwidth
canvas(".c") -insertofftime(100) -insertontime(150) -insertwidth(2);
invalidcommand entry(".e") -invalidcommand("bell");

Note: also acepts functions and function objects without parameters.

ipadx
ipady
pack(".b") -ipadx(5) -ipady("2c");
jump scrollbar(".sb") -jump(true);
justify label(".l") -justify(center);
label ".m" << add(command) -menulabel("select me");
labelanchor labelframe(".lf") -text("hello") -labelanchor(nw);
labelwidget labelframe(".lf") -labelwidget(".lf.w");
length scale(".s") -length(100);
listvariable - (not implemented)
lmargin1
lmargin2
".t" << tag(configure, "mytag") -lmargin1(20) -lmargin2(5);
maxundo textw(".t") -undo(true) -maxundo(100);
menu ".m" << add(cascade) -submenu(".m.m");
menubutton(".mb") -submenu(".mb.m");
offrelief checkbutton(".cb") -offrelief(raised);
offset ".t" << tag(configure, "mytag") -offset(2);
offvalue
onvalue
checkbutton(".cb") -offvalue(-1) -onvalue(1);
opaqueresize panedwindow(".pw") -opaqueresize(true);
orient panedwindow(".pw") -orient(horizontal);
overrelief button(".b") -overrelief(raised);
overstrike ".t" << tag(configure, "mytag") -overstrike(true);
padx
pady
pack(".b") -padx(5) -pady(5);
palette images(create, photo) -gamma(1.5) -palette(10);
postcommand menu(".m") -postcommand(fun); // fun is any function or function object with no parameters
readonlybackground ".e" << configure() -readonlybackground("gray");
relheight
relwidth
place(".b") -relheight(0.5) -relwidth(0.5);
relief frame(".f") -relief(raised);
relx
rely
place(".b") -relx(10) -rely(20);
repeatdelay
repeatinterval
button(".b") -repeatdelay(100);
button(".b") -repeatinterval(100);
resolution scale(".s") -resolution(10);
rmargin ".t" << tag(configure, "mytag") -rmargin(20);
sashcursor
sashpad
sashrelief
sashwidth
panedwindow(".pw") -sashcursor("mycursor") -sashpad(5) -sashrelief(raised) -sashwidth(10);
screen toplevel(".w") -screen("scr");
scrollregion canvas(".c") -scrollregion(10, 20, 30, 40);
selectbackground
selectborderwidth
selectforeground
canvas(".c") -selectbackground("blue") -selectborderwidth(3) -selectforeground("red");
selectcolor
selectimage
checkbutton(".cb") -selectcolor("blue");
checkbutton(".cb") -selectimage(myimage);
setgrid listbox(".lb") -setgrid(true);
show ".e" << configure() -show("*");
showhandle panedwindow(".pw") -showhandle(true);
showvalue scale(".s") -showvalue(true);
shrink "photo1" << copy("photo2") -shrink();
sliderlength
sliderrelief
scale(".s") -sliderlength(100) -sliderrelief(raised);
spacing1
spacing2
spacing3
textw(".t") -spacing1(5) -spacing2(6) -spacing3(7);
state button(".b") -state(disabled);
subsample "photo1" << copy("photo2") -subsample(3, 4);
tabs textw(".t") -tabs("2c left 4c 6c center");
tag ".t" << dump(txt(1,0), end) -tags();
takefocus entry(".e") -takefocus(true);
tearoff
tearoffcommand
menu(".m") -tearoff(true) -tearoffcommand(fun);

Note: fun is any function or function object with appropriate parameter types.

text button(".b") -text("press me");
textvariable string s;
entry(".e") -textvariable(s);

Note: also works with int and double.

title menu(".m") -tearoff(true) -title("My menu");
to "photo1" << copy("photo2") -to(10, 20, 30, 40);
scale(".s") -from(10) -to(100);
troughcolor scale(".s") -troughcolor("blue");
underline button(".b") -text("hello") -underline(1);
validate
validatecommand
bool mycheck(string const &s) { /* ... */ }
entry(".e") -validate(key) -validatecommand(mycheck, valid_P);

Note: validatecommand accepts any function or function object returning something convertible to bool, long, double or string and with the set of parameters compatible with the list of validation specifiers.

value
values
radiobutton(".r") -value("second");
spinbox(".sp") -values("a b c");
variable int i;
checkbutton(".cb") -variable(i);
visual - (not implemented)
width button(".b") -width(40);
wrap spinbox(".sp") -from(0) -to(10) -wrap(true);
wraplength label(".l") -wraplength(20);
x
y
place(".b") -x(10) -y(20);
xscrollcommand
yscrollcommand
canvas(".c") -xscrollcommand("xcmd") -yscrollcommand("ycmd");
xscrollincrement
yscrollincrement
canvas(".c") -xscrollincrement(10) -yscrollincrement(20);
zoom "photo1" << copy("photo2") -zoom(3, 4);

Constants

In addition to the fact that every option name and some of the command names can be used as string constants, there is also a set of constants defined in the cpptkconstants.x file.


Loose bits and pieces

  1. To help creating indexes (entry, canvas, text, etc.), the following helper functions are provided:
    • at(x, y) creates string "@x,y"
    • at(x) creates string "@x"
    • txt(ln, ch) creates string "ln.ch"

  2. The std::string rgb(r, g, b); function formats the "#rrggbb" string, useful for color definitions.

  3. To specify substitutions in the bind command, the following specifiers can be used (equivalent to % substitutions in Tcl/Tk):

    event_A
    event_b
    event_D
    event_f
    event_h
    event_k
    event_K
    event_m
    event_N
    event_s
    event_T
    event_w
    event_W
    event_x
    event_X
    event_y
    event_Y


    Note: the number and types of parameters in the function or function object used for callback must be compatible with the specifiers.

  4. To specify sibstitutions in the validatecommand option of the entry widget, the following specifiers can be used (equivalent to % substitutions in Tcl/Tk):

    valid_d
    valid_i
    valid_P
    valid_s
    valid_S
    valid_v
    valid_V
    valid_W


    Note 1: the callback function or function object has to return something that is convertible to bool, int, double or std::string.
    Note 2: the number and types of parameters in the function or function object used for callback must be compatible with the specifiers.

  5. Defining callbacks.
    Every functor with compatible set of parameters can be used in options and functions like command, after, etc. In addition, the following are provided:
    • template <class Functor> std::string callback(Functor f); - this function will register a callback and return a name for respective Tcl procedure. This name can be used in those places where the callback is expected, but the registration takes place only once.
    • void deleteCallback(std::string const &name); - this function unregisters a callback with the given name.
    • class CallbackHandle; - this class ca be used as a RAII wrapper for registering and unregistering callbacks. The get() method is used to retrieve the callback name.

  6. Conversions.
    A C++/Tk expression, after execution, can leave some result in the interpreter. This result can be retrieved by converting the whole expression into one of the following types:
    • std::string()
    • int
    • double
    • Tk::Point (a class with two int members: x and y)
    • Tk::Box (a class with four int members: x1, y1, x2 and y2)
    • std::pair<T1, T2>
    • std::vector<T>

  7. Additional helper functions:
    • template <typename T> std::string linkVar(T &t); - used to create an explicit link between C++ variable and Tcl variable. Returns the name of Tcl variable.
    • template <typename T> void unLinkVar(T &t); - used to remove the linking between C++ variable and Tcl variable.
    • class LinkHandle; - can be used as a RAII wrapper for linking variables. The get() method is used to retrieve the name of respective Tcl variable.
    • std::string eval(std::string const &str); - this function forces evaluation of the given script. Can be used when everything else fails. :-)
    • void init(char *argv0); - should be called at the beginning of the C++/Tk program with the value of argv[0].
    • void runEventLoop(); - runs the Tk event toop. Normally never returns.
    • void setDumpStream(std::ostream &os); - set the stream for dumping Tcl/Tk commands. Can be useful for testing and debugging.

Compiling

The whole C++/Tk library consists of the following files: cpptk.h, cpptk.cc, cpptkoptions.x, cpptkconstants.x, base/cpptkbase.h and base/cpptkbase.cc.

The cpptk.cc and base/cpptkbase.cc files can be compiled to the object files and reused in many projects, just like in the example programs. They may also be compiled to the form of an archive or a shared library.

It is important to note that the *.x files are not compilable and should not be included as project files in the IDE. However, they should be placed in a directory where they can be visible by the preprocessor while compiling the project (they are #included by cpptk.h and cpptk.cc).

Dependencies

The C++/Tk library depends on the Boost library (see http://www.boost.org/). Any recent version of this library should work fine. Note that it is not necessary to compile or install Boost - it is enough to just upack it in some place and provide the relevant path when compiling C++/Tk programs. Boost is also not needed for the compiled programs to run.
Of course, the Tcl/Tk header files and libraries are also necessary. Any recent version of Tcl/Tk should work fine.

Compiling options

Two separate options can be used when compiling C++/Tk programs:

Both options can be useful when testing and debugging C++/Tk programs and are used in tests that accompany the library.

Unix, GNU/Linux

On Unix-like systems, the following command is enough to compile a one-file C++/Tk program (shown for FreeBSD):

$ g++ myprog.cc cpptk.cc base/cpptkbase.cc -o myprog -I/usr/local/include/tcl8.4 -I/usr/local/include/tk8.4 -I/usr/X11R6/include -I/usr/local/include/boost_1_33_0 -L/usr/local/lib -ltcl84 -ltk84 -pthread

Depending on the specific Unix system, it may be necessary to use different search paths or threading option (-lpthread is typical on Linux, but may not be needed at all).

Note also that a decent g++ compiler is necessary (in particular, g++ 2.95 or 2.96 will not work).