tcl/tk
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.
(source)
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 0.8.6 % 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
- https://wiki.tcl-lang.org/page/keysyms
- https://github.com/tcltk/tk/blob/master/generic/tkText.c
InsertChars
- https://stackoverflow.com/a/23766838/1091982
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
So:
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