8

I'm looking for a way to draw a thin line around a multipart shape. For a normal shape, an easy way to do this is to use preaction to draw an even thicker line around the existing shape. Unfortunately, somehow the preaction seems to happen after the node parts are drawn in multipart shapes, giving an unwanted inner line.

Below is a minimal working example. You can see for the regular box on the right, there is just a thin orange line around the outside. However, for the multipart "contents box" on the left, there is a second, inner orange box. My question is how to get rid of this inner box. I'm not necessarily wedded to multipart nodes if there's a better way to draw these boxes, but I would like them to be a node so I can draw arrows to them. (BTW, I know that for the regular box I can do this without a preaction, I just used one to illustrate what I'm trying to do to multipart nodes.)

enter image description here

\documentclass[convert]{standalone}

\usepackage{tikz}
\usetikzlibrary{shapes.multipart}

\begin{document}

\begin{tikzpicture}[
    contents box/.style={
      rounded corners,
      rectangle split, rectangle split parts=2,
      rectangle split draw splits=false,
      rectangle split part fill={orange!50, white},
      every one node part/.style={
        font=\sffamily\bfseries\small,
      },
      draw=orange!50, very thick,
      preaction={draw=orange, ultra thick},
    },
    regular box/.style={
      font=\sffamily\bfseries\small,
      rounded corners,
      fill=orange!50,
      very thick, draw=orange!50,
      preaction={draw=orange, ultra thick},
    }
  ]
  \node[contents box] {
    \nodepart{one} box
    \nodepart{two} contents
  };
  \node[regular box] at (2,0) { box };
\end{tikzpicture}

\end{document}
3

If all multipart boxes are like in example, it's also possible to use a tcolorbox to draw them.

It's possible to use them as node contents into a tikzpicture, but it's also possible to include them into any text and draw arrows to them with remember or remember as help (see How to draw arrows between colourboxes).

\documentclass[tikz,border=2mm]{standalone}
\usepackage[most]{tcolorbox}
\newtcbox{\mybox}[1]{
    colbacktitle=orange!50,
    colback=white,
    colframe=orange!50,
    halign title=center, 
    fonttitle=\bfseries\sffamily\small, 
    fontupper=\small,
    coltitle=black,
    title=#1,
    boxrule=1.6pt, 
    enhanced,borderline={1.2pt}{-1.2pt}{orange},
    enlarge bottom by=1.2pt,
    enlarge top by=1.2pt,
    enlarge right by=1.2pt,
    enlarge left by=1.2pt,}
\begin{document}
\begin{tikzpicture}
\node[inner sep=0pt] (A) at (0,0)  {\mybox{box}{contents}};
\node[inner sep=0pt] (B) at (3,1) {\mybox{box}{contents}};

\draw[orange,ultra thick] (A.north) to[out=85,in=180](B.west);
\end{tikzpicture}
\end{document}

enter image description here

1

You could just draw it afterwards. For example, if the node is named b, then:

  \path [draw=orange, thin, rounded corners] (b.south west) rectangle (b.north east);

will draw an appropriate path:

drawn box

There isn't any obvious way to do this as part of the specification of the node itself.

You can, however, make things more convenient by defining a pic to do everything in one step:

    contents pic/.pic={
      \node (a) [contents box] {#1};
      \path [draw=orange, thin, rounded corners] (a.south west) rectangle (a.north east);
    },

Then you can write, for example:

  \pic at (1.75,0) { contents pic={
    \nodepart{one} box
    \nodepart{two} contents
    }
  };

to draw a clone of the earlier node + path. For comparison:

comparison

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{shapes.multipart}
\begin{document}
\begin{tikzpicture}[
    contents box/.style={
      rounded corners,
      rectangle split,
      rectangle split parts=2,
      rectangle split draw splits=false,
      rectangle split part fill={orange!50, white},
      every one node part/.style={
        font=\sffamily\bfseries\small,
      },
      draw=orange!50,
      very thick,
    },
    regular box/.style={
      font=\sffamily\bfseries\small,
      rounded corners,
      fill=orange!50,
      very thick,
      draw=orange!50,
      preaction={draw=orange, ultra thick},
    },
    contents pic/.pic={
      \node (a) [contents box] {#1};
      \path [draw=orange, thin, rounded corners] (a.south west) rectangle (a.north east);
    },
  ]
  \node (b) [contents box] {
    \nodepart{one} box
    \nodepart{two} contents
  };
  \path [draw=orange, thin, rounded corners] (b.south west) rectangle (b.north east);
  \pic at (1.75,0) { contents pic={
    \nodepart{one} box
    \nodepart{two} contents
    }
  };
  \node[regular box] at (3.25,0) { box };
\end{tikzpicture}
\end{document}
  • Could it be drawn afterwards in the style using append style or append after command? – Alenanno Jan 16 '16 at 23:24
  • @Alenanno Hmmm.... Thanks. I hadn't thought of that but will take a look. For now, I've added a pic version which does everything in one go. – cfr Jan 16 '16 at 23:32
  • I should learn more about pic. It seems to improve many things. – Alenanno Jan 16 '16 at 23:33
  • 1
    append after command={\pgfextra{\draw[orange, thin, rounded corners] (\tikzlastnode.south west) rectangle (\tikzlastnode.north east);}} :P – Alenanno Jan 16 '16 at 23:43
  • @Alenanno: \tikzlastnode is a good idea! – user3188445 Jan 16 '16 at 23:48
1

Here is a solution based on @Alenanno's key idea of using \tikzlastnode inside append after command. The remaining tricky part is that you have to set outer sep of the multipart node knowing that later it will be traced by an ultra thick line, and then also compensate for that outer sep value. Ultra thick lines are 1.6pt, so half that (the appropriate outer sep) is 0.8pt.

\documentclass[convert]{standalone}

\usepackage{tikz}
\usetikzlibrary{shapes.multipart}

\begin{document}

\begin{tikzpicture}[
    contents box/.style={
      rounded corners,
      rectangle split, rectangle split parts=2,
      rectangle split draw splits=true,
      rectangle split part fill={orange!50, white},
      every one node part/.style={ font=\sffamily\bfseries\small },
      draw=orange!50, very thick,
      outer sep=0.8pt, % 1/2 ultra-thick line width
      append after command={
        \pgfextra{
          \draw[orange, ultra thick, rounded corners] 
          ([shift={(0.8pt,0.8pt)}] \tikzlastnode.south west)
          rectangle
          ([shift={(-0.8pt,-0.8pt)}] \tikzlastnode.north east)
          ;}
    }},
    regular box/.style={
      font=\sffamily\bfseries\small,
      rounded corners,
      fill=orange!50,
      very thick, draw=orange!50,
      preaction={draw=orange, ultra thick},
    }
  ]
  \node[contents box] {
    \nodepart{one} box
    \nodepart{two} contents
  };
  \node[regular box] at (2,0) { box };
\end{tikzpicture}

\end{document}

enter image description here

  • you have more problems with that but if you are not going to use them on a colored path then I guess it is OK. – percusse Feb 16 '16 at 10:31

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.