我正在尝试使用 TikZ 构建实体关系图。我曾使用过这个优秀的答案由 Mark Wibrow 给出。但是,我更希望在矩阵中给出实体名称,并用一条线将其与其属性分开,而不是作为矩阵上方的标签。
我曾想过,我应该尝试以编程方式在矩阵开头插入标题行,而不是设置标签文本,但我不知道该怎么做。我花了一些时间阅读 PGF/TikZ 手册的各个部分并试验代码,但我找不到任何有用的东西,目前我发现 PGF/TikZ 相当令人困惑。
我发现我可以row 1/.style
在entity/.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}