如何以编程方式将标题行插入 TikZ 矩阵

如何以编程方式将标题行插入 TikZ 矩阵

我正在尝试使用 TikZ 构建实体关系图。我曾使用过这个优秀的答案由 Mark Wibrow 给出。但是,我更希望在矩阵中给出实体名称,并用一条线将其与其属性分开,而不是作为矩阵上方的标签。

我曾想过,我应该尝试以编程方式在矩阵开头插入标题行,而不是设置标签文本,但我不知道该怎么做。我花了一些时间阅读 PGF/TikZ 手册的各个部分并试验代码,但我找不到任何有用的东西,目前我发现 PGF/TikZ 相当令人困惑。

我发现我可以row 1/.styleentity/.code \tikzset命令中使用它来处理第一行。我尝试使用row 1/.style={node contents={#1}}它来设置其中的文本,但我猜这在稍后\properties使用该命令时会被覆盖。

以下是来自其他答案的代码:

\documentclass[a4paper]{article} 
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\usetikzlibrary{shadows}
\usetikzlibrary{calc}

\makeatletter
\pgfarrowsdeclare{crow's foot}{crow's foot}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}%
  \pgfarrowsrightextend{+.5\pgflinewidth}%
}
{
  \pgfutil@tempdima=0.5pt%
  \advance\pgfutil@tempdima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0pt}{-6\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-6\pgfutil@tempdima}{0pt}}%
  \pgfpathlineto{\pgfqpoint{0pt}{6\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}


\tikzset{
    entity/.code={
        \tikzset{
            label={#1},
            name=#1,
            inner sep=0pt,
            every entity/.try,
            fill=white
        }%
        \def\entityname{#1}%

    },
    entity anchor/.style={matrix anchor=#1.center},
    every entity/.style={
            draw,
    },
    every property/.style={
        inner xsep=0.25cm, inner ysep=0.125cm, anchor=west, text width=1in
    },
    zig zag to/.style={
        to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget)}
    },
    zig zag to/.default=0.5,
    one to many/.style={
        -crow's foot, zig zag to
    },
    many to one/.style={
        crow's foot-, zig zag to
    },
    many to many/.style={
        crow's foot-crow's foot, zig zag to
    }
}
\def\property#1{\node[name=\entityname-#1, every property/.try]{#1};}
\def\properties{\begingroup\catcode`\_=11\relax\processproperties}
\def\processproperties#1{\endgroup%
    \def\propertycode{}%
    \foreach \p in {#1}{%
        \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\propertycode%
            \expandafter\expandafter\expandafter{\expandafter\propertycode\expandafter\property\expandafter{\p}\\}%
    }%
    \propertycode%
}

\begin{document}
\begin{tikzpicture}
\matrix [entity=articles] {
    \properties{
        classkey, 
        class_type,
        class_desc
    }
};
\end{tikzpicture}

\end{document}

其结果为:

相反,我想要这样的东西:

答案1

在这个例子中,你可以做一个几乎微不足道的手术。由于这些东西的尺寸是固定的,你所要做的就是绘制标签节点的边界,并使用与属性节点相同的尺寸。更详细地说,我所做的就是替换

 label={#1},

经过

label={[text width=1in,draw,inner xsep=0.25cm,yshift=-\pgflinewidth]#1},

如果你想让这段文字居中,请这样做

label={[text width=1in,draw,inner xsep=0.25cm,yshift=-\pgflinewidth,align=center]#1},

我是否一定建议这样做是另一个问题。

\documentclass[a4paper]{article} 
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\usetikzlibrary{shadows}
\usetikzlibrary{calc}

\makeatletter
\pgfarrowsdeclare{crow's foot}{crow's foot}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}%
  \pgfarrowsrightextend{+.5\pgflinewidth}%
}
{
  \pgfutil@tempdima=0.5pt%
  \advance\pgfutil@tempdima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0pt}{-6\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-6\pgfutil@tempdima}{0pt}}%
  \pgfpathlineto{\pgfqpoint{0pt}{6\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}


\tikzset{
    entity/.code={
        \tikzset{
            label={[text width=1in,draw,inner xsep=0.25cm,yshift=-\pgflinewidth]#1},
            name=#1,
            inner sep=0pt,
            every entity/.try,
            fill=white
        }%
        \def\entityname{#1}%

    },
    entity anchor/.style={matrix anchor=#1.center},
    every entity/.style={
            draw,
    },
    every property/.style={
        inner xsep=0.25cm, inner ysep=0.125cm, anchor=west, text width=1in
    },
    zig zag to/.style={
        to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget)}
    },
    zig zag to/.default=0.5,
    one to many/.style={
        -crow's foot, zig zag to
    },
    many to one/.style={
        crow's foot-, zig zag to
    },
    many to many/.style={
        crow's foot-crow's foot, zig zag to
    }
}
\def\property#1{\node[name=\entityname-#1, every property/.try]{#1};}
\def\properties{\begingroup\catcode`\_=11\relax\processproperties}
\def\processproperties#1{\endgroup%
    \def\propertycode{}%
    \foreach \p in {#1}{%
        \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\propertycode%
            \expandafter\expandafter\expandafter{\expandafter\propertycode\expandafter\property\expandafter{\p}\\}%
    }%
    \propertycode%
}

\begin{document}
\begin{tikzpicture}
\matrix [entity={articles}] {
    \properties{
        classkey, 
        class_type,
        class_desc
    }
};
\end{tikzpicture}

\end{document}

在此处输入图片描述

更新:只是为了好玩,可以使用多部分节点的替代方案,您可以在其中访问其元素。

\documentclass[a4paper]{article} 
\usepackage{tikz}
\usepackage{etoolbox}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{positioning}
\usetikzlibrary{shadows.blur}
\usetikzlibrary{calc}


\def\numtext#1{% from https://tex.stackexchange.com/a/67926/121799
  \ifcase#1\or one\or two\or three\or four\or five\or six\or seven\or eight\or nine\or ten\or
eleven\or twelve\or thirteen\or fourteen\or fifteen\or sixteen\or seventeen\or eighteen\or nineteen\or twenty\or Lots\fi}


\makeatletter % from https://tex.stackexchange.com/a/88336/121799
\newcommand{\GetCurrentNodeName}{\tikz@fig@name}
\makeatother
\tikzset{Line/.style={
        path picture={
            \draw (\GetCurrentNodeName.text split west) -- (\GetCurrentNodeName.text split east);
        }}}


% based on \Bytes from https://tex.stackexchange.com/a/67926/121799
\newcommand{\Properties}[2][]{
\def\nodecontents{}%
\foreach[count=\l] \k in {#2} {
    \xappto{\nodecontents}{\noexpand\nodepart{\numtext{\l}}\k}
    \xdef\mycount{\l}
}
\node [rectangle split,rectangle split parts=\mycount,draw, rectangle split draw splits=false,
Line,alias=X,#1] {\nodecontents};
}


\makeatletter
\pgfarrowsdeclare{crow's foot}{crow's foot}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}%
  \pgfarrowsrightextend{+.5\pgflinewidth}%
}
{
  \pgfutil@tempdima=0.5pt%
  \advance\pgfutil@tempdima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0pt}{-6\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-6\pgfutil@tempdima}{0pt}}%
  \pgfpathlineto{\pgfqpoint{0pt}{6\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}


\tikzset{
    zig zag to/.style={
        to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget)}
    },
    zig zag to/.default=0.5,
    one to many/.style={
        -crow's foot, zig zag to
    },
    many to one/.style={
        crow's foot-, zig zag to
    },
    many to many/.style={
        crow's foot-crow's foot, zig zag to
    }
}

\begin{document}

\begin{tikzpicture}
\Properties[name=leftnode,blur shadow,fill=white]{articles,classkey,class\_type,class\_desc}
\Properties[above right=3cm of leftnode,name=aboverightnode]{enlightened beings,ducks,
marmots,koala bears}
\Properties[right=4cm of leftnode,name=rightnode]{keys,house keys,
car keys,burrow keys}
\draw [many to one] (aboverightnode)     to (leftnode.two east);
\draw [many to one] (rightnode)     to (leftnode.three east);
\end{tikzpicture}

\end{document}

在此处输入图片描述

相关内容