mastodon warning! may contain trace amounts of Lisp


Table of Contents

This is a collection of notes written as I learn how to use Tcl/Tk, so it must be far from error-free; beware the dog of imprecision.

There is a shell called wish that spawns an empty window also, and that can be controlled through the shell.

1. text

There are several widgets. Take text for instance:

text .texto -font {"Iosevka Term Slab" -18}

This creates an instance of text called .texto (is the dot really needed? I don’t think so) with the font thus stipulated. The instance sits in limbo until you make it manifest by pack .texto. There is more than one way of putting things on a window.


The white thingy is all we have accomplished so far.

Now, how to get rid of it?

pack forget .texto


1.1. inserting

Good. Now we pack it again. Now, to put text in it, one uses .texto insert 1.0 [string] This 1.0 is the index of where the text should go. Why the dot? It does the same as .texto insert end "mimimi".

So this next sequence of commands leaves us with the following:

pack .texto
.texto insert 1.0 "tralala"
.texto insert 1.0 "tralala"
.texto insert end "mimimi"
.texto insert end "\nxuxu\tlalala\nlala\tshushushu"


1.2. reading

Since the field is editable, it shouldn’t be excessively hopeful to think there should be a way to get its contents. There is, get.

Given that the widget adds a newline (\n) at the end of the text, one can escape the trouble of getting rid of it by get~ting the string from the beginning to its ~end -1. The whole command is this:

.texto get 1.0 end-1c

The command dump -all 1.0 end does something similar, but weirder:

text {tralalatralalamimimi
} 1.0 text {xuxu        lalala
} 2.0 text {lala        shushushu} 3.0 mark current 3.14 mark insert 3.14 mark\
 tk::anchor1 3.14 text {
} 3.14

Now, .texto configure gives all the options associated with it:

{-autoseparators autoSeparators AutoSeparators 1 1}
{-background background Background #ffffff #ffffff}
{-bd -borderwidth}
{-bg -background}
{-blockcursor blockCursor BlockCursor 0 0}
{-borderwidth borderWidth BorderWidth 1 1}
{-cursor cursor Cursor xterm xterm}
{-endline {}
{-exportselection exportSelection ExportSelection 1 1}
{-fg -foreground}
{-font font Font TkFixedFont {"Iosevka Term Slab" -18}}
{-foreground foreground Foreground #000000 #000000}
{-height height Height 24 24}
{-highlightbackground highlightBackground HighlightBackground #d9d9d9 #d9d9d9}
{-highlightcolor highlightColor HighlightColor #000000 #000000}
{-highlightthickness highlightThickness HighlightThickness 1 1}
{-inactiveselectbackground inactiveSelectBackground Foreground #c3c3c3 #c3c3c3}
{-insertbackground insertBackground Foreground #000000 #000000}
{-insertborderwidth insertBorderWidth BorderWidth 0 0}
{-insertofftime insertOffTime OffTime 300 300}
{-insertontime insertOnTime OnTime 600 600}
{-insertunfocussed insertUnfocussed InsertUnfocussed none none}
{-insertwidth insertWidth InsertWidth 2 2}
{-maxundo maxUndo MaxUndo 0 0}
{-padx padX Pad 1 1}
{-pady padY Pad 1 1}
{-relief relief Relief sunken sunken}
{-selectbackground selectBackground Foreground #c3c3c3 #c3c3c3}
{-selectborderwidth selectBorderWidth BorderWidth 0 0}
{-selectforeground selectForeground Background #000000 #000000}
{-setgrid setGrid SetGrid 0 0}
{-spacing1 spacing1 Spacing 0 0}
{-spacing2 spacing2 Spacing 0 0}
{-spacing3 spacing3 Spacing 0 0}
{-startline {}
{-state state State normal normal}
{-tabs tabs Tabs {}
{-tabstyle tabStyle TabStyle tabular tabular}
{-takefocus takeFocus TakeFocus {}
{-undo undo Undo 0 0}
{-width width Width 80 80}
{-wrap wrap Wrap char char}
{-xscrollcommand xScrollCommand ScrollCommand {}
{-yscrollcommand yScrollCommand ScrollCommand {}

Behold the arcane features of an ancient object of power.

1.3. the insertion cursor

A text widget displays one or more lines of text and allows that text to be edited. Text widgets support four different kinds of annotations on the text, called tags, marks, embedded windows or embedded images. Tags allow different portions of the text to be displayed with different fonts and colors. In addition, Tcl commands can be associated with tags so that scripts are invoked when particular actions such as keystrokes and mouse button presses occur in particular ranges of the text. See TAGS below for more details.


The blinking thingy is called insertion cursor, and it’s a flag called insert. How to manipulate it? Thusly:

.texto mark set insert 1.0

1.4. read-only

It becomes read-only with the disabled state. One can select text, but not insert any, not even programatically. For that you have to change the state to normal.

text .texto
pack .texto
texto insert end "lalala shushushu"
.texto configure -state disabled
# this does nothing:
texto insert end "lalala shushushu"
.texto configure -state normal
# but this works:
texto insert end "lalala shushushu"

2. mouse

Read the mouse position: (source)

package require Tk 8.5
set curWindow [lindex [wm stackorder .] end]
# Everything below will work with anything from Tk 8.0 onwards
set x [expr {[winfo pointerx .] - [winfo rootx $curWindow]}]
set y [expr {[winfo pointery .] - [winfo rooty $curWindow]}]
tk_messageBox -message "the mouse is at ($x,$y) in window $curWindow"

It reads even when the mouse is outside the window.

3. fonts

font configure TkDefaultFont -family "Noto Sans" -size 16

4. widgets

label .lalala1 -text "label"
pack .lalala1
button .lalala2 -text "a button"
pack .lalala2
entry .lalala3 -text "an entry here"
pack .lalala3
message .lalala4 -text "a\nlong\nmessage"
pack .lalala4
text .lalala5
.lalala5 insert end "a text area"
pack .lalala5


5. themes

Usually they are packages. You can query all packages by package names. Packages are recondite creatures that live in the directories listed by tclsh when given the command join $auto_path; (on $autopath) /usr/lib/tcl8.6 and /usr/lib in my case. Or $tcl_pkgPath?

There is a collection of themes here, and one gets them by using a version control system called fossil ( homepage, comments by the author), of which I never heard before this. After some incantations, it spits some directories, each with a pkgIndex.tcl, so each its own package.

There are no packages that I can see inside the two directories above, so I’ll put them in some directory and add it to $auto_path:

$ wish
% pkg_mkIndex /medha/sandbox/ttk-themes/themes/clearlooks
% lappend tcl_pkgPath /medha/sandbox/ttk-themes/themes
/usr/lib /medha/sandbox/ttk-themes/themes
% package names
http ttk::theme::classic tcl::tommath TclOO tcltest ttk::theme::default
Ttk msgcat zlib Tcl ttk::theme::clam platform tile Tk ttk::theme::alt
% package require tile
% package names
http ttk::theme::classic tcl::tommath TclOO tcltest ttk::theme::default
Ttk msgcat zlib Tcl ttk::theme::clam platform tile Tk ttk::theme::alt
% pkg_mkIndex /medha/sandbox/ttk-themes/themes/clearlooks
% package names

Themes for regular widges are completely separated from the ttk:: ones.

ttk::style theme names

6. reading keys

proc insert {thing} {.c insert end thing
.c insert end \n}
~bind . <KeyPress> {puts %K}~ → "Escape"
~bind . <KeyPress> {puts %k}~ → 9

Removing a binding from one bindtag does not mean that the event will not be processed; a binding on another bindtag might still pick it up. Trying to hack around the other bindtags to fool the code is not going to be satisfactory. However, if a binding on one tag finishes with a break, it prevents further bindtags from being tried; it terminates processing early. This makes it easy to mask specific events: bind .c <Up> break


text .c
pack .c
proc insert {thing} {puts $thing; .c insert end $thing; .c insert end \n}
bind .c <KeyPress> {insert %k; break}
ttk::button .button -command {.c delete 1.0 end} -text "clear"
pack .button

7. hover tooltip

8. images

9. in Common Lisp

· © Edgard Bikelis (eſb) created using Emacs 29.0.50 (Org mode 9.5.3) ·
· created: 2020-03-24 last modified: 2020-05-23 ·