Tcl/Tk bindings for Dear ImGui (partial), ImPlot and ImPlot3D : fast interactive 2D / 3D plots (GPU, OpenGL) in a Tk widget.
- Tcl/Tk >= 9.0
- Tcl cffi >= 2.0
- TkGL : OpenGL widget for Tk
- A C library with Dear ImGui, ImPlot and ImPlot3D, through cimgui, cimplot and cimplot3d
- Windows, Linux, macOS support.
- Download the package of your platform from the GitHub Releases :
it contains
implot.tk, the C library andTkGLbuilt for Tcl/Tk 9. - Or build everything yourself, see lib/BUILD.md.
package require implot.tk
# 1. Creates the surface (no Tk widget yet) and sets its options.
set f [implottk::surface new]
$f SetOptions -width 600 -height 400 -title "Line" -axisName {x y}
# 2. Adds the commands, evaluated at each frame.
$f AddPlotCmd {
implottk::static {
set xs [implottk::doubleToPointer {0 1 2 3 4}]
set ys [implottk::doubleToPointer {0 1 0.5 4 1}]
}
implot::PlotLine_doublePtrdoublePtr "Line 1" $xs $ys 5 {LineColor {x 1 y 0 z 0 w 1}}
}
# 3. Render creates the Tk widget and returns its path, 4. pack it.
pack [$f Render] -fill both -expand 1- The package is implot.tk, its commands are in the
implottknamespace (implottk::surface,implottk::static...). $f Render ?-parent path?creates the widget the first time and returns its path$f destroydestroys the surface and its widget.- See demo/multiple_surfaces.tcl for several surfaces.
Set with $f SetOptions option value ?option value ...? (before or after Render) :
| Option | Value | Default |
|---|---|---|
-width, -height |
size of the widget (pixels) | 600, 400 |
-title |
title of the plot added by the surface (##... : hidden) |
##title |
-axisName |
names of the axes {x y} of the plot added by the surface |
{} |
-background |
color of the window {r g b}, {} : color of the theme |
{} |
-color |
ImGui colors {windowBackground {r g b} popupBackground {r g b} text {r g b}} |
- |
-colorPlot |
ImPlot colors {plotBackground .. frameBackground .. axisText .. legendBackground .. legendText ..} |
- |
-fonts |
{file.ttf size}, or a Tk font {TkDefaultFont ?size?} (see Fonts) |
ImGui font |
-idleFps |
frames per second without event (see Rendering) | 10 |
-framebufferScale |
pixels per Tk unit (e.g. 2.0 on a retina display) | 1.0 |
Note
Dear ImGui is an immediate mode GUI : the scripts are evaluated at each frame, AddGuiCmd
scripts first (widgets : sliders, checkboxes...), then AddPlotCmd scripts (plots). Every function
declared in src/imgui/funcs.tcl, src/implot/funcs.tcl and src/implot3d/funcs.tcl can be called.
The style of an item is an ImPlotSpec, written as a dictionary (missing fields keep their
default value) :
implot::PlotLine_doublePtrdoublePtr "Line 2" $xs $ys 5 {
LineColor {x 0 y 0.5 z 1 w 1}
LineWeight 2
Marker ImPlotMarker_Circle
Flags ImPlotLineFlags_Segments
}When a script calls implot::BeginPlot itself, the other ImPlot functions must only be called
when it returns true.
implottk::static initializes the data only the first time :
$f AddPlotCmd {
# a script evaluated only the first time...
implottk::static {
set rectXMin 0.0025 ; set rectYMin 0.0
set rectXMax 0.0045 ; set rectYMax 0.5
}
# ... or pairs 'name value'.
implottk::static flags 0
imgui::CheckboxFlags_UintPtr "NoCursors" flags 1
if {[implot::BeginPlot "##Main"]} {
implot::DragRect 0 rectXMin rectYMin rectXMax rectYMax {x 1 y 0 z 1 w 1} $flags clicked hovered held
implot::EndPlot
}
}- The state of the widgets (value of a checkbox, position of a drag tool...) is kept in the
variables given to the functions (
inoutparameters).
-
implottk::doubleToPointer $list: C array of doubles (uintToPointer: unsigned int, forimplot3d::PlotMesh_doublePtr). -
implottk::updatePointer $pointer $list: writes new values in an existing array (data changed at each frame, no memory allocated). -
Data added as they come (timer, socket, file...) : outside of the plot script, in arrays that grow when they are full, then
$f redraw. See demo/adddata.tcl. -
Getters :
PlotLineG,PlotScatterG,PlotStairsG,PlotDigitalG,PlotBarsG,PlotShadedG(two getters) take a Tcl command called for each index, which returns{x y}. It is called several times by point and by frame : for thousands of points, the arrays are faster. See demo/getters.tcl.proc spiral {i} { set r [expr {0.9 * $i / 1000.0}] list [expr {0.5 + $r * cos($i * 0.03)}] [expr {0.5 + $r * sin($i * 0.03)}] } $f AddPlotCmd {implot::PlotLineG "Spiral" spiral 1000}
A surface is rendered at 60 frames per second for 0.5 s after each Tk event (mouse, keyboard,
resize...), then at -idleFps frames per second :
$f SetOptions -idleFps 60 ;# animations, data changed at each frame
$f SetOptions -idleFps 0 ;# rendered only on events
$f redraw ;# new frame, for example after a change of the dataDear ImGui uses dynamic fonts : a font is loaded once and its glyphs are created on demand
for any size (no glyph ranges, no atlas to build, PushFont takes a size) :
$f SetOptions -fonts [list /path/to/font.ttf 16] ;# default font of the surface (pixels)
$f AddGuiCmd {
implottk::static {
set atlas [imgui::ImGuiIO getnative [imgui::GetIO_Nil] Fonts]
set mono [imgui::ImFontAtlas_AddFontFromFileTTF $atlas /path/to/mono.ttf]
}
imgui::PushFont $mono 24 ;# a font and its size
imgui::Text "%s" {string "24 px"}
imgui::PopFont
imgui::PushFont NULL 12 ;# the current font, another size
imgui::Text "%s" {string "12 px"}
imgui::PopFont
}A Tk font can also be given : implottk searches its file (Windows only for now, registry of the
fonts), without size the size of the Tk font is used. When the file is not found, the default
Dear ImGui font is used :
$f SetOptions -fonts TkDefaultFont ;# same font as the Tk widgets
$f SetOptions -fonts {TkFixedFont 14} ;# 14 pixelsThe strings are sent to Dear ImGui in UTF-8 (accents, symbols...), including the variadic
arguments {string value}. See demo/fonts.tcl.
The implot3d namespace gives the functions of ImPlot3D
(each surface has its own context). A script that calls implot3d::BeginPlot is not wrapped in a
plot by the surface. The style of an item is a dict of ImPlot3DSpec fields :
$f AddPlotCmd {
implottk::static {
set xs [implottk::doubleToPointer {0 0.25 0.5 0.75 1}]
set ys [implottk::doubleToPointer {0 0.5 1 0.5 0}]
set zs [implottk::doubleToPointer {0 0.1 0.4 0.9 1}]
}
if {[implot3d::BeginPlot "3D" {x -1 y -1}]} {
implot3d::SetupAxes "x" "y" "z"
implot3d::PlotLine_doublePtr "line" $xs $ys $zs 5 {Marker ImPlot3DMarker_Circle}
implot3d::EndPlot
}
}- line, shaded, scatter, stairs, stems, infinite lines
- bars (vertical / horizontal / stacked, groups), error bars
- pie charts, heatmaps, 1D / 2D histograms
- bubbles, polygons, digital plots, text, dummy
- getters (PlotLineG)
- images
- 3D (ImPlot3D) : line, scatter, triangle, quad, surface and mesh plots, text
Run them with tclsh demo/<name>.tcl (see demo).
- macOS : On a retina display set
-framebufferScale 2.0(not tested yet). - Calling an
ImPlotfunction outside of a plot (whenBeginPlotreturned false) can crash the application. - And probably many others...
implot.tk is covered under the terms of the MIT license. The packages also contain Dear ImGui, ImPlot, ImPlot3D, cimgui, cimplot, cimplot3d and TkGL, under their own licenses : see THIRD_PARTY_NOTICES.md.
- 15-Sep-2022 : 1.0b0
- 19-Sep-2022 : 1.0b1
- Add SubplotsSizing + SubplotItemSharing (drag & drop) demo.
- Cosmetic changes + adding
imguifunctions.
- 01-Oct-2022 : 1.0b2
- Add examples.
- Fix bug when my frame was mapped or unmapped.
- Rename
win32.tclfile byuser32.tcl
- 08-Oct-2026 : 1.0
- Full redesign of the library.
- More examples and GitHub Actions.