4

I have a command for putting a text in a rounded corner box with bg-color. It uses tikz node:

\newcommand\mybox[1]{\tikz[overlay]\node[fill=blue!20, rectangle, rounded corners=2pt]{#1};}

When I use this box inside a forest node, the node doesn't appear. Please could you tell me the reason? and how to achieve the same effect in forest and still having nice formatting options like tikz?

enter image description here

MWE:

\documentclass{article}
\usepackage{forest}
\newcommand\mybox[1]{\tikz[overlay]\node[fill=blue!20, rectangle, rounded corners=2pt]{#1};}

\begin{document}

\tikz\node[fill=blue!20,rectangle, rounded corners=2pt]{123}; 

\mybox{inside box}

\begin{forest}
for tree={align=center, parent anchor=south, child anchor=north, l sep=5mm}
[\tikz\node{eee}; node1  
 [\mybox{2} node2
  [\mybox{3} node3]
  [\mybox{4} node4]
 ]
]
\end{forest}

\end{document}
  • What do you want? a label like 123 beside every tree node? or every tree node like label 123? – Ignasi Feb 11 '16 at 19:56
  • a label with a bg-color inside a node: \node{\mybox{label} text}; – Fibo Kowalsky Feb 11 '16 at 21:43
  • 1
    Note that nesting tikzpictures is generally dodgy. It will work in simple cases, but more often fail in more complex ones. That's the problem here, I think. You are nesting tikzpictures without controlling, for example, when things are expanded and so on, and that is not going to work. – cfr Feb 11 '16 at 22:10
7

As mentioned by AboAmmar, the trick here is to use forest's keys to get the result you want.

For convenience, we can define a TikZ style and a corresponding forest one.

\tikzset{
  my blue box/.style={fill=blue!20, rectangle, rounded corners=2pt},
}
\forestset{
  my blue label/.style={
    label={[my blue box]left:#1},
    s sep+=10pt,
  }
}

As AboAmmar shows, the TikZ style can be passed in for tree if the settings should simply apply to every node of the tree as such.

\begin{forest}
  for tree={
    align=center,
    parent anchor=south,
    child anchor=north,
    l sep=5mm,
    my blue box,
  }
  [eee node1
    [2 node2
     [3 node3]
     [4 node4]
    ]
  ]
\end{forest}

styled nodes

Or you can use the forest style to easily specify the contents of labels to be created to the left of specific nodes in the tree.

\begin{forest}
  for tree={
    align=center,
    parent anchor=south,
    child anchor=north,
    l sep=5mm,
  }
  [node1, my blue label=eee
    [node2, my blue label=2
     [node3, my blue label=3]
     [node4, my blue label=4]
    ]
  ]
\end{forest}

specific labels

In some cases, the labels can also be added automatically based on information about the node's location etc. in the tree. For example, based on the node's level or placement relative to its siblings or, in this case, on the node's internal id.

This default label can then be overridden for specific nodes using the my blue label style used earlier.

\begin{forest}
  for tree={
    align=center,
    parent anchor=south,
    child anchor=north,
    l sep=5mm,
    label/.wrap pgfmath arg={% specify default label for nodes
      {[my blue box]left:#1}
    }{int(id()-1)},
    s sep+=10pt,
  }
  [node1, my blue label=eee% override default label for this node
    [node2
     [node3]
     [node4]
    ]
  ]
\end{forest}

auto-labelling with optional override

Another, similar option is to add the labels using TikZ code after the tree is drawn. We can add a couple more forest styles to facilitate this.

\forestset{
  ...
  my blue postscript/.style={
    tikz={\node [my blue box, anchor=east] at (.west) {#1};},
    s sep+=10pt,
  },
  auto blue postscripts/.style={
    my blue postscript/.wrap pgfmath arg={##1}{int(id()-1)},
  }
}

Then auto blue postscripts will add the label or labels automatically, as before, and my blue postscript=<content> will add a specific label, if automated labelling isn't activated or if the automatic label should be overridden in a particular case.

Then

\begin{forest}
  for tree={
    align=center,
    parent anchor=south,
    child anchor=north,
    l sep=5mm,
    auto blue postscripts,
  }
  [node1, my blue postscript=eee
    [node2
     [node3]
     [node4]
    ]
  ]
\end{forest}

automated labelling with override option using TikZ code directly

However, there is no real advantage to this more complex option in this case that I can see, so I'd recommend the method relying on label above.

Complete code:

\documentclass[tikz, border=10pt, multi]{standalone}
\usepackage{forest}
\begin{document}
\tikzset{
  my blue box/.style={fill=blue!20, rectangle, rounded corners=2pt},
}
\forestset{
  my blue label/.style={
    label={[my blue box]left:#1},
    s sep+=10pt,
  },
  my blue postscript/.style={
    tikz={\node [my blue box, anchor=east] at (.west) {#1};},
    s sep+=10pt,
  },
  auto blue postscripts/.style={
    my blue postscript/.wrap pgfmath arg={##1}{int(id()-1)},
  }
}
\begin{forest}
  for tree={
    align=center,
    parent anchor=south,
    child anchor=north,
    l sep=5mm,
    my blue box,
  }
  [eee node1
    [2 node2
     [3 node3]
     [4 node4]
    ]
  ]
\end{forest}
\begin{forest}
  for tree={
    align=center,
    parent anchor=south,
    child anchor=north,
    l sep=5mm,
  }
  [node1, my blue label=eee
    [node2, my blue label=2
     [node3, my blue label=3]
     [node4, my blue label=4]
    ]
  ]
\end{forest}
\begin{forest}
  for tree={
    align=center,
    parent anchor=south,
    child anchor=north,
    l sep=5mm,
    label/.wrap pgfmath arg={
      {[my blue box]left:#1}
    }{int(id()-1)},
    s sep+=10pt,
  }
  [node1, my blue label=eee
    [node2
     [node3]
     [node4]
    ]
  ]
\end{forest}
\begin{forest}
  for tree={
    align=center,
    parent anchor=south,
    child anchor=north,
    l sep=5mm,
    auto blue postscripts,
  }
  [node1, my blue postscript=eee
    [node2
     [node3]
     [node4]
    ]
  ]
\end{forest}
\end{document}
  • Thanks for the complete answer. Previously I was putting labels in the content of a node, but since there is special syntax for labeling I will stick to that. – Fibo Kowalsky Feb 11 '16 at 22:20
  • 1
    It will be easier, I think, even if it takes getting used to. Just remember to increase s sep a bit to make room for the labels. – cfr Feb 11 '16 at 22:23
1

Just add to your tree options the following: rounded corners=2pt, fill=blue!20 and there is no need for the \mybox{} command you've created.

\documentclass{article}
\usepackage{forest}
\begin{document}

\begin{forest}
for tree={align=center, parent anchor=south, child anchor=north, l sep=5mm, rounded corners=2pt, fill=blue!20}
[node1  
 [ node2
  [ node3]
  [ node4]
 ]
]
\end{forest}

\end{document}

enter image description here

  • Thanks but this is not what I want to get in the end. A node should contain a text in box and a text without box. See the mwe: [\mybox{2} node2 – Fibo Kowalsky Feb 11 '16 at 21:38
  • The \tikz\node{eee}; in the root node is spurious. (Unsurprisingly, it has no effect; surprisingly, it doesn't produce an error.) Hope you don't mind: I edited so I could vote this up without checking back first. (Laziness....) – cfr Feb 11 '16 at 21:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.