![如何从节点内的表绘制指向另一个节点的箭头](https://linux22.com/image/347912/%E5%A6%82%E4%BD%95%E4%BB%8E%E8%8A%82%E7%82%B9%E5%86%85%E7%9A%84%E8%A1%A8%E7%BB%98%E5%88%B6%E6%8C%87%E5%90%91%E5%8F%A6%E4%B8%80%E4%B8%AA%E8%8A%82%E7%82%B9%E7%9A%84%E7%AE%AD%E5%A4%B4.png)
我正在尝试从表格单元格到节点绘制特定箭头。这是我到目前为止所做的:
我正在尝试得到这个:
这是我的代码:
\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{tikz}
\usetikzlibrary{tikzmark,calc}
\usetikzlibrary{arrows,automata}
\begin{document}
\begin{tikzpicture}[->,>=stealth,node distance=4cm,semithick]
\tikzstyle{every state}=[draw=black,text=black,minimum size=2cm]
\node[state]at (0,0)(0) {
\begin{tabular}{|c|}
\hline
\rowcolor{gray!50}
5 \\\hline
13 \\\hline
14 \\\hline
\end{tabular}
};
\node[state]at (-4,-4)(1) {
\begin{tabular}{|c| }
\hline
\cellcolor{gray!50} 1 \\\hline
11 \\\hline
12 \\\hline
\end{tabular}
};
\node[state](2) at (-2,-8){
\begin{tabular}{|c| }
\hline
\cellcolor{gray!50} 2 \\\hline
17 \\\hline
18 \\\hline
\end{tabular}
};;
\node[state](3) at (4,-4) {
\begin{tabular}{|c| }
\hline
\cellcolor{gray!50} 3 \\\hline
15 \\\hline
16 \\\hline
\end{tabular}
};
\node[fill=gray!50,state](4) at (6,-8) {4 jump };
%\node[fill=gray!50,draw=black,text=black,minimum size=2cm](6) at (6,-8) { };
\node[draw=black,thick,circle,inner sep=4.5pt](6) at (6,-8) {4 jump };
\node[state](5) at (-6,0) {
\begin{tabular}{|c| }
\hline
\cellcolor{gray!50} 5 \\\hline
17 \\\hline
18 \\\hline
\end{tabular}
};
\draw (0) -- (1);
\draw (0) -- (3);
\draw (1) -- (3);
\draw (1) -- (2);
\draw (2) -- (4);
\draw[transform canvas={xshift=4pt,yshift=2pt}] (2)--(1);
\draw (3) -- (2);
\draw (3) -- (4);
\draw (5) -- (1);
\draw (5) -- (3);
\end{tikzpicture}
\end{document}
有没有办法做到这一点?
答案1
使用multipart
形状代替表格:
\documentclass[tikz, margin=3mm]{standalone}
\usetikzlibrary{arrows,
automata,
calc,
fit, % <-- added
shapes.multipart, % <-- added
tikzmark}
\begin{document}
\begin{tikzpicture}[->,>=stealth, semithick,
node distance = 4cm,
state/.style = {shape=rectangle split, draw,
rectangle split parts=3,
rectangle split part fill={gray!30,white},
minimum width=20mm},
fitnode/.style = {shape=circle, draw, inner sep=1pt,outer sep=0pt,
node contents={}}
]
\node (0) [state] { 5 \\
\nodepart{two} 13 \\
\nodepart{three} 14
};
\node (10) [fitnode, fit=(0)];
\node (1) [state] at (-4,-4) { 1 \\
\nodepart{two} 11 \\
\nodepart{three} 12
};
\node (11) [fitnode,fit=(1)];
\node (2) [state] at (-2,-8) { 2 \\
\nodepart{two} 17 \\
\nodepart{three} 18
};
\node (12) [fitnode,fit=(2)];
\node (3) [state] at (4,-4) { 3 \\
\nodepart{two} 15 \\
\nodepart{three} 16
};
\node (13) [fitnode,fit=(3)];
\node (4) [shape=circle,draw, fill=gray!50,
double=gray!50,double distance=2mm,
align=center,
inner sep=3mm,outer sep=1.5mm] at (4,-8) {4\\ jump};
\node (5) [state] at (-6,0) { 5 \\
\nodepart{two} 17 \\
\nodepart{three} 18
};
\node (15) [fitnode,fit=(5)];
%
\draw (0.west) edge (11)
(0.east) edge (13)
(1.east) edge (13)
(1.south) edge (12)
(2) edge (4)
(2.three west) edge [out=180,in=270] (11.south)
(3.south) edge (12)
(3.east) edge [out=0,in=0] (4)
(5.south) edge (11)
(5.east) -- (13);
\end{tikzpicture}
\end{document}
附录:
考虑 吉列尔梅·扎诺泰利注释和对现有代码的一些进一步改进,其中利用positioning
TikZ 库控制节点的相对定位node distance
并重新定义state
样式。为了简化节点的相对定位,它们被重命名。通过这些措施,代码变得更加简洁:
\documentclass[tikz, margin=5mm]{standalone}
\usetikzlibrary{arrows,
automata,
calc,
fit, % <-- added
positioning, % <-- added
shapes.multipart, % <-- added
}
\begin{document}
\begin{tikzpicture}[semithick,
node distance = 24mm and 12mm,
state/.style args = {#1 #2 #3}%
{shape=rectangle split, draw,
rectangle split parts=3,
rectangle split part fill={gray!30,white},
minimum width=17mm,
node contents={\nodepart{one} #1 % <-- added
\nodepart{two} #2
\nodepart{three}#3},
append after command=\pgfextra{ % <-- added
\node (1\tikzlastnode) [fitnode, fit=(\tikzlastnode)];}%%
},
jump/.style = % <-- added
{shape=circle,draw, fill=gray!50,
double=gray!50,double distance=2mm,
align=center,
inner sep=3mm, outer sep=1.5mm
},
fitnode/.style =
{shape=circle, draw,
inner sep=1pt,outer sep=0pt,
node contents={}}
]
\node (1) [state=5 17 18];
\node (2) [state=1 11 12,below right=of 1];
\node (3) [state=5 13 14,above right=of 2];
\node (4) [state=3 15 16,below right=of 3];
\node (5) [state=2 17 18,below right=of 2];
\node (6) [jump,right=of 5] {4\\ jump};
%
\draw[-stealth]
(1.south) edge (12)
(1.east) edge (14)
(2.east) edge (14)
(2.south) edge (15)
(3.west) edge (12)
(3.east) edge (14)
(4.south) edge (15)
(4.east) edge [out=0,in=0] (6)
(5.east) edge (6)
(5.west) to [out=180,in=270] (12);
\end{tikzpicture}
\end{document}
答案2
我同意 Jan 的观点,你画的图看起来好多了。不过这得你自己判断,我们只是来帮忙的。:)
所以,这似乎是一件matrix
好事。tikz 中的 A\matrix
是一个包含其他节点的大节点,它的美妙之处在于自动命名。假设您A
使用 命名矩阵:\matrix (A) {...};
矩阵内的所有节点A
都将具有类似 的名称A-<row>-<column>
。由于矩阵本身是一个节点,因此您可以使用anchor, above, inner sep
等。
最后,节点的定义\matrix
就像它们是一张表一样,因此您的语法几乎不需要修改,只需删除\begin \end{tabular}
和\hline
s 就足够了。让我们开始 MWE 吧!
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,automata}
\begin{document}
\begin{tikzpicture}[->,>=stealth,
node distance=4cm,semithick,
every state/.style={
draw=black,
text=black,
minimum size=2cm},
row 1/.style={fill=gray!50},
state matrix/.style={
state,
matrix of nodes,
row sep=0pt,
column sep=0pt,
nodes={draw, rectangle, minimum height=0pt, minimum width=3em}}]
\matrix[state matrix] (0) at (0,0) {
|[row 1]| 5\\
13\\
14\\};
\matrix[state matrix] (1) at (-4,-4) {
|[row 1]| 1 \\
11 \\
12 \\};
\matrix[state matrix] (2) at (-2,-8){
|[row 1]| 2 \\
17 \\
18 \\};
\matrix[state matrix] (3) at (4,-4) {
|[row 1]| 3 \\
15 \\
16 \\};
\node[state,fill=gray!50,double=gray!50, double distance=5pt] (4) at (6,-8) {4 jump };
\matrix[state matrix] (5) at (-6,0) {
|[row 1]| 5 \\
17 \\
18 \\
};
\foreach \i in {0,...,5} \node[above] at (\i.north) {\i};
\draw[->]%
(5-2-1.east) edge (3)
(5-3-1.south) edge (1)
(0-2-1.west) edge (1)
(0-2-1.east) edge (3)
(1-2-1.east) edge (3)
(1-3-1.east) edge (2)
;
\end{tikzpicture}
\end{document}
该matrix
库提供了matrix of nodes
样式,这减少了必要的数量\node
(有关更多信息,请查看手册),使用该样式,Matrix 内的所有节点都会接收提供的样式nodes={sty keys}
,因此我为它们都提供了,minimum width=3em
但您可以调整该值。此外,我double
在4 jump
节点中使用了,而不是使用不同的大小绘制两次。我画了一些边,但剩下的留给你,因为我现在没时间了!此外,还有一个\foreach
命名状态矩阵,仅供参考绘制边,完成后只需将其删除即可。
对于互相跳跃的线路,请检查TikZ 中两条线的交点实际上并未连接Mark Wibrow 在那里给出了一个非常简洁的答案,我对它做了一些修改(那里也回答了这个问题)。