Fill a bounding box behind text in Makie

Is there now a way to fill a text bounding box? This question was asked a couple of years ago, but there was not a direct implementation at that time and a lot has changed since then.

Basically, what I’d like to do is have a box of arbitrary dimension surrounding either a text! object, Label, or similar object and choose the border color and line width, as well as the fill color.

One solution might be just to draw a Box and then draw the text on top. But I’m having issues with aligning the box with the text and also making sure the box is behind the text.

Not directly, yet. But you can use the Box way with a slight workaround usually, which is to put the box and the label inside their own little GridLayout. The GridLayout itself, and therefore also the Box, will shrink to the Label size plus padding, then you can move it around using align. tellwidth and tellheight false on the layout means the big layout will not shrink to its size, depending on what you want you might enable that though.

 f = Figure()
 gl = GridLayout(f[1, 1], tellwidth = false, tellheight = false, halign = :right, valign = :bottom)
 Box(gl[1, 1], color = :bisque, strokecolor = :black, strokewidth = 2)
 Label(gl[1, 1], "A Label\nin a Box", padding = (10, 10, 10, 10))
 Axis(f[1, 2])
 Axis(f[2, 1])
 Axis(f[2, 2])
 f

Thanks! That worked reasonably well. Is there a way to float the box slightly above the bottom? It would be nice to have it float instead of attached to the axis.

I can’t share my data, but I whipped up an example demonstrating the type of data I’m working with and the kind of plots I’m making (two-dimensional infrared spectroscopy (2DIR)) for others to try.

Note: I’m using some custom theming on my macOS retina display (package here) so your font sizing, etc. will be different.

using GLMakie
# using SomeMakieThemes
GLMakie.activate!(inline=false)
# set_theme!(theme_manuscript_retina())

function lorentz2d(x, y, A, ω_0, Γ)
    data = zeros(length(x), length(y))
    for i in eachindex(x)
        for j in eachindex(y)
            data[i, j] = A * Γ ./ ((x[i] .- ω_0) .^2 + (y[j]) .^2 .+ Γ^2)
        end
    end
    data
end

x = -10:0.5:10
y = -10:0.5:10
Γ = 2
A = 40
ω1 = -2
ω2 = 2
z = lorentz2d(x, y, A, ω1, Γ) .- lorentz2d(x, y, A, ω2, Γ) .+ 0.05 * randn(length(x), length(y))

fig = Figure()
DataInspector()

ax = Axis(fig[1, 1], xlabel = "Probe frequency (arb.)", ylabel = "Pump frequency (arb.)", 
    xticks = x[1]:2:x[end],
    yticks = y[1]:2:y[end],
    )
colsize!(fig.layout, 1, Aspect(1, 1.0))
gl = GridLayout(fig[1, 1], 
    tellwidth = false, 
    tellheight = false, 
    halign = :center, 
    valign = :bottom,
    )

levels = minimum(z)-2:2:maximum(z)+2
ct = contourf!(x, y, z, levels=levels, colormap = :RdBu)
contour!(x, y, z, levels=levels, linewidth = 0.5, color = :black)
Colorbar(fig[0, 1], ct, label = "Intensity (arb.)",
    ticks = [-17, 0, 15],
    vertical = false,
    ticksvisible = false
    )
xlims!(ax, -7, 7)
ylims!(ax, -7, 7)

Box(gl[1, 1], color = :white, strokecolor = :black, strokewidth = 2)
Label(gl[1, 1], "10 ps",
    fontsize = 42,
    padding = (10, 10, 20, 20),
    )

resize_to_layout!(fig)
fig
# save("lorentz2DIR.png", fig,)

You could either set it fractionally like valign = 0.05 on the GridLayout or by giving it a padding like alignmode = Outside(10)

Ah yes, that works well. Thanks!

Do you think this will be implemented directly in the near future? If not, I can write up an example for the Makie docs showing how to implement this workaround.

1 Like