How to draw complex nodes in tikz?

Probably you can do it with the matrix library:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows}

\begin{document}

\begin{tikzpicture}
[   mymatrix/.style={draw,thick,minimum width=1.0cm,minimum height=1.0cm,inner sep=0,anchor=south west}
]
    \matrix[matrix of nodes, nodes=mymatrix] (firstmatrix) at (0,0)
    {   q & w & e \\
        a & s & d \\ 
    };
    \matrix[matrix of nodes, nodes=mymatrix] (secondmatrix) at (10,0)
    {   i & o & p \\
        j & k & l \\ 
    };
    \draw[-latex] (firstmatrix.20) -- (secondmatrix.200);
\end{tikzpicture}

\end{document}

enter image description here


Edit 1: As Altermundus stated, the inner lines are double lines which is not desirable, so here's a solution using nodes and manually drawn lines (I'll try to automate this):

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows}

\begin{document}

\begin{tikzpicture}
[   mynode/.style={thick,minimum width=1.0cm,minimum height=1.0cm,inner sep=0,anchor=south west},
    mymatrix/.style={draw,inner sep=0}
]
    \matrix[matrix of nodes, nodes=mynode, mymatrix] (firstmatrix) at (0,0)
    {   \node (q) {q}; & w & \node (e) {e}; \\
        \node (a) {a}; & s & \node (d) {d}; \\ 
    };
    \draw (q.south west) -- (e.south east);
    \draw (q.north east) -- (a.south east);
    \draw (e.north west) -- (d.south west);

    \matrix[matrix of nodes, nodes=mynode, mymatrix] (secondmatrix) at (10,0)
    {   \node (i) {i}; & o & \node (p) {p}; \\
        \node (j) {j}; & k & \node (l) {l}; \\ 
    };
    \draw (i.south west) -- (p.south east);
    \draw (i.north east) -- (j.south east);
    \draw (p.north west) -- (l.south west);

    \draw[-latex] (firstmatrix.20) -- (secondmatrix.200);
\end{tikzpicture}

\end{document}

enter image description here

Edit 1.1: As Andrew Stacey remarked, it is of cause not neccessary to explicitely put nodes. You're in a matrix of nodes Neo, and not a slave. The individual cells all have names of the form matrixname-rownumber-columnnumber, and one can use this. The following produces exactly the same result as before:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows}

\begin{document}

\begin{tikzpicture}
[   mynode/.style={thick,minimum width=1.0cm,minimum height=1.0cm,inner sep=0,anchor=south west},
    mymatrix/.style={draw,inner sep=0},
    myline/.style={shorten <=0.2pt, shorten >=0.2pt},
]
    \matrix[matrix of nodes, nodes=mynode, mymatrix] (firstmatrix) at (0,0)
    {   q & w & e \\
        a & s & d \\ 
    };
    \draw[myline] (firstmatrix-1-1.south west) -- (firstmatrix-1-3.south east);
    \draw[myline] (firstmatrix-1-1.north east) -- (firstmatrix-2-1.south east);
    \draw[myline] (firstmatrix-1-3.north west) -- (firstmatrix-2-3.south west);

    \matrix[matrix of nodes, nodes=mynode, mymatrix] (secondmatrix) at (10,0)
    {   i & o & p \\
        j & k & l \\ 
    };
    \draw[myline] (secondmatrix-1-1.south west) -- (secondmatrix-1-3.south east);
    \draw[myline] (secondmatrix-1-1.north east) -- (secondmatrix-2-1.south east);
    \draw[myline] (secondmatrix-1-3.north west) -- (secondmatrix-2-3.south west);

    \draw[-latex] (firstmatrix.20) -- (secondmatrix.200);
\end{tikzpicture}

\end{document}

Edit 2: Another way to "avoid" the double outline is to draw both the nodes and the matrix, but the latter with the double line width:

\tikzset{
    mynode/.style={line width=0.25pt, draw, minimum width=1.0cm, minimum height=1.0cm, inner sep=0, anchor=south west},
    mymatrix/.style={line width=0.5pt, draw, inner sep=0},
    myline/.style={shorten <=0.2pt, shorten >=0.2pt},
}

\begin{tikzpicture}
    \matrix[matrix of nodes, nodes=mynode, mymatrix] (firstmatrix) at (0,0)
    {   q & w & e \\
        a & s & d \\ 
    };

\end{tikzpicture}

enter image description here


You can also use the infamous \tikzmark solution which allows one to compose the tables outside (or inside) of the tikzpicture environment, and mark the two points you want to connect, and then draw the arrow between them.

So, with the c data entry defined as c\tikzmark{left}, and the j data entry is defined as \tikzmark{right}j, one can use \DrawArrow[<draw_options>]{left}{right} with different draw options to obtain:

enter image description here

Note:

  • This does require two runs. First one to determine the locations, and the second to do the drawing.

  • The \tikzmark is from Adding a large brace next to a body of text.

Code:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture] \node (#1) {};}

\newcommand*{\DrawArrow}[3][]{%
    % #1 = draw options
    % #2 = left point
    % #3 = right point
    \begin{tikzpicture}[overlay,remember picture]
        \draw [-latex, shorten <= 0.25cm, shorten >= 0.30cm, #1] ($(#2)+(0,0.5ex)$) to ($(#3)+(0,0.25ex)$);
    \end{tikzpicture}%
}%

\begin{document}
\begin{tabular}{| c | c | c |}\hline
    a & b & c\tikzmark{left} \\\hline
    d & e & f \\\hline
\end{tabular}
\hspace*{2.0cm}
\begin{tabular}{| c | c | c |}\hline
    g & h & i \\\hline
    \tikzmark{right}j & k & l \\\hline
\end{tabular}
%
\DrawArrow{left}{right}
\end{document}

This is an other idea based on Peter Grill's answer (I didn't even think of using a tabular when writing my first answer, so thanks for reminding me that there are some non-TikZ constructs one could use). It doesn't use \tikzmark (which otherwise is awesome, but in my humble opinion not needed here) and puts the tabulars in nodes instead, so you can use the degree notion (node.degree) to specify where to draw your arrows:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,arrows}

\newcommand{\mytab}[2]% alignment, content
{   \begin{tabular}{#1}
        #2
    \end{tabular}
}

\begin{document}

\begin{tikzpicture}
    \node[inner sep=0] (one) {\mytab{|c|c|c|}{\hline g & h & i \\ \hline j & k & l \\ \hline}};
    \node[inner sep=0,right=2cm of one.east] (two) {\mytab{|c|c|c|}{\hline a & b & c \\ \hline d & e & f \\ \hline}};
    \draw[-latex] (one.15) to[out=0,in=180] (two.195);
\end{tikzpicture}

\end{document}

enter image description here

Tags:

Tikz Pgf