在 tikzset 中参数化节点文本

在 tikzset 中参数化节点文本

我有以下绘制链接列表的代码

最初,它将节点文本打印为靠在节点的右边缘。将\hspace*{-3pt}每个文本放在前面解决了这个水平错位问题。

tikz 中的链表

\documentclass[a4paper,openany,14pt]{extbook}

\usepackage{tikz}
\usetikzlibrary{shapes.multipart,chains,positioning,arrows,calc,arrows.meta}

\newcommand{\columnratio}{0.62} % to be able to fit the TikZ drawing
\newcommand{\columnseper}{12pt} % inside small sections

\begin{document}

\pgfmathsetlengthmacro{\ourwidth}{\columnratio * \linewidth - \columnseper}

\tikzset{thebox/.style = {
    % args={2}, % Nope
    rectangle split, rectangle split horizontal,
    rectangle split parts=2,
    very thick, draw=black!100,
    align=center,font=\footnotesize,
    text width=0.047 * \ourwidth,
    minimum width=0.040 * \ourwidth,
    text height=0.023 * \ourwidth,
    text depth=2.7pt,
    inner xsep=0.30cm,
    % inner xsep west = 0.10cm % Nope
    node distance = 4mm,
% \nodepart[]{one} text = {\hspace*{-3pt}#1}, % Attempt to parameterize the text
% \nodepart[]{two} text = {\hspace*{-3pt}#2},
} }

\tikzset{arr/.style = {very thick,{Circle[length=6pt,sep=-3pt]}-{Stealth} } }
\noindent\begin{tikzpicture}[start chain=1,start chain=2,start chain=3,start chain=4]
\tikzset{every node}=[font=\small\ttfamily]
      
\node[rectangle, on chain=1,inner xsep=0.05cm,](ORIG){\footnotesize 1511};

\node (A) [thebox,on chain=1,right=0.0cm of ORIG]
     {\nodepart[]{one}\hspace*{-3pt}1111 \nodepart[]{two}}; % comment \hspace*{-3pt}1111

\node (B) [thebox, on chain=1,] % right=0.4cm of A,
     {\nodepart[]{one}\hspace*{-3pt} \nodepart[]{two}\hspace*{-3pt}};

\node (C) [thebox, on chain=1,] % right=0.4cm of B,
     {\nodepart[]{one}\hspace*{-3pt}2111 \nodepart[]{two}};

\node (D) [thebox, on chain=1,] % right=0.4cm of C
     {\nodepart[]{one} \nodepart[]{two}\hspace*{-3pt}0000};

\node (E) [thebox, on chain=3,below=0.55cm of D] at (9.65, -0.3)
     {\nodepart[]{one}\hspace*{-3pt}6700 \nodepart[]{two}\hspace*{-3pt}};

\node (F) [thebox, on chain=3,] % right=0.4 of E
     {\nodepart[]{one}\hspace*{-3pt}8000 \nodepart[]{two}\hspace*{-3pt}0000};
     
\node (G) [thebox, on chain=2,below=1.4cm of B] at (4.6, -0.5)
      {\nodepart[]{one}\hspace*{-3pt}3422 \nodepart[]{two}\hspace*{-3pt}};

\node (H) [thebox, on chain=2,] %at (4.5, -0.5) % right=0.4cm of G
     {\nodepart[]{one}\hspace*{-3pt} \nodepart[]{two}\hspace*{-3pt}};

\node (I) [thebox, on chain=4,below=0.6cm of H] at (7.6, -2.5)
      {\nodepart[]{one}\hspace*{-3pt}4000 \nodepart[]{two}\hspace*{-3pt}};

\node (J) [thebox, on chain=2,] % right=0.4cm of H 
      {\nodepart[]{one}\hspace*{-3pt}5321 \nodepart[]{two}\hspace*{-3pt}0000};
      
\node (K) [thebox, on chain=4,] % right=0.4cm of I
     {\nodepart[]{one}\hspace*{-3pt}7222 \nodepart[]{two}\hspace*{-3pt}0000};


 \draw[arr] ($(A.two)!0.32!(A.east)$) -- (B.west);
 \draw[arr] ($(B.west)!0.10!(B.east)$) |- (G.west);
 \draw[arr] ($(B.two)!0.32!(B.east)$) -- (C.west);
 \draw[arr] ($(C.two)!0.32!(C.east)$) -- (D.west);
 \draw[arr] ($(D.west)!0.10!(D.east)$) |- (E.west);
 \draw[arr] ($(E.two)!0.32!(E.east)$) -- (F.west);
 \draw[arr] ($(G.two)!0.32!(G.east)$) -- (H.west);
 \draw[arr] ($(H.west)!0.08!(H.east)$) |- (I.west);
 \draw[arr] ($(H.two)!0.32!(H.east)$) -- (J.west);
 \draw[arr] ($(I.two)!0.32!(I.east)$) -- (K.west);
\end{tikzpicture}
\end{document}

为了避免手动重复,我考虑参数化 tikzset=thebox/.style{... 我添加的节点文本

  \nodepart[]{one} text = {\hspace*{-3pt} #1 }
  \nodepart[]{two} text = {\hspace*{-3pt} #2}

毫不奇怪,它们没有起作用。我查过类似的帖子,比如这个 有没有办法使用 \tikzset 设置多部分节点的文本?

n args={2}并且我在旁边添加了,thebox/.style但这导致了编译错误。我查阅了 TikZ 手册,它有 1300 多页 (!),没有关于这个特定问题的明确示例。

如何正确参数化里面的节点文本\tikzset

答案1

您可以使用设置节点文本node contents,例如

\tikzset{thebox/.style n args={2}{
        node contents={\nodepart{one}\hspace*{-3pt}#1\nodepart{two}\hspace*{-3pt}#2},
    }
}

进而\node (C) [thebox={2111}{},on chain=1];


这是基于您的代码的 MWE。我允许自己做一些修改以使其更短。框大小仅由和决定text widthminimum height您不需要\hspace*{-3pt}在这里。此外,对于每个框,我定义了两个坐标x-onex-two以简化箭头。

在此处输入图片描述

\documentclass[a4paper,openany,14pt]{extbook}

\usepackage{tikz}
\usetikzlibrary{shapes.multipart,chains,positioning,arrows.meta,calc}

\begin{document}

\tikzset{thebox/.style n args={2}{
        rectangle split,
        rectangle split horizontal,
        rectangle split parts=2,
        very thick,
        draw=black,
        align=center,
        text width=25, % adjust box width here
        minimum height=18, % adjust box height here
        node distance=4mm,
        node contents={\nodepart{one}#1\nodepart{two}#2},
        append after command={% define x-one and x-two coordinates for connecting arrows
            \pgfextra{\edef\currentnode{\tikzlastnode}}
            (\currentnode.two north|-\currentnode.east) coordinate (\currentnode-two)
            ($(\currentnode.west)!0.1!(\currentnode.east)$) coordinate (\currentnode-one)
        },
    },
    arr/.style={very thick,{Circle[length=6pt,sep=-3pt]}-{Stealth}},
    every node/.append style={font=\footnotesize\ttfamily},
}

\noindent\begin{tikzpicture}[start chain=1,start chain=2,start chain=3,start chain=4]

\node[rectangle,on chain=1,inner xsep=0.05cm,] (ORIG) {1511};

\node (A) [thebox={1111}{},on chain=1,right=0.0cm of ORIG];
\node (B) [thebox={}{},on chain=1];
\node (C) [thebox={2111}{},on chain=1];
\node (D) [thebox={}{0000},on chain=1];
\node (E) [thebox={6700}{},on chain=3,below right=0.55cm and 0.75cm of D.south west];
\node (F) [thebox={8000}{0000},on chain=3];
\node (G) [thebox={3422}{},on chain=2,below right=1.4cm and 0.75cm of B.south west];
\node (H) [thebox={}{},on chain=2];
\node (I) [thebox={4000}{},on chain=4,below right=0.6cm and 0.75cm of H.south west];
\node (J) [thebox={5321}{0000},on chain=2];
\node (K) [thebox={7222}{0000},on chain=4];

\draw[arr] (A-two) -- (B);
\draw[arr] (B-two) -- (C);
\draw[arr] (C-two) -- (D);
\draw[arr] (D-one) |- (E);
\draw[arr] (E-two) -- (F);
\draw[arr] (B-one) |- (G);
\draw[arr] (G-two) -- (H);
\draw[arr] (H-one) |- (I);
\draw[arr] (I-two) -- (K);
\draw[arr] (H-two) -- (J);
\end{tikzpicture}
\end{document}

答案2

我觉得这个问题是由于text width设置太窄造成的align=center, inner xsep=0.30cm。例如,如果宽度足够,text width=1cm输出看起来就很好(因此不需要\hspace{-3pt})。

此外,为了从节点部分的中心正确启动箭头two,我改变了每一个

\draw[arr] ($(X.two)!0.32!(A.east)$) -- (Y.west);

\draw[arr] ($(X.one split)!0.5!(A.east)$) -- (Y.west);

完整示例

\documentclass[a4paper,openany,14pt]{extbook}

\usepackage{tikz}
\usetikzlibrary{shapes.multipart,chains,positioning,arrows,calc,arrows.meta}

\newcommand{\columnratio}{0.62} % to be able to fit the TikZ drawing
\newcommand{\columnseper}{12pt} % inside small sections

\begin{document}

\pgfmathsetlengthmacro{\ourwidth}{\columnratio * \linewidth - \columnseper}

\tikzset{
  thebox/.style = {
    rectangle split,
    rectangle split horizontal,
    rectangle split parts=2,
    very thick,
    draw=black!100,
    align=center,
    text width=1cm,
    text height=1.5ex,
    text depth=.35ex,
    inner xsep=0.08cm,
    node distance=2mm and 4mm,
  },
  arr/.style = {
    very thick,
    {Circle[length=6pt,sep=-3pt]}-{Stealth},
  },
}


\noindent
\begin{tikzpicture}[
  start chain/.list={1,2,3,4},
  nodes={font=\footnotesize\ttfamily}]
  
  \node[on chain=1] (ORIG) {1511};
  
  \node (A) [thebox, on chain=1, right=0cm of ORIG]
       {\nodepart{one}1111 \nodepart{two}};
  
  \node (B) [thebox, on chain=1,] % right=0.4cm of A,
       {\nodepart[]{one} \nodepart[]{two}};
  
  \node (C) [thebox, on chain=1,] % right=0.4cm of B,
       {\nodepart[]{one} 2111 \nodepart[]{two}};
  
  \node (D) [thebox, on chain=1,] % right=0.4cm of C
       {\nodepart[]{one} \nodepart[]{two} 0000};
  
  \node (E) [thebox, on chain=3, below right=.3cm and -1.5cm of D]
       {\nodepart[]{one} 6700 \nodepart[]{two}};
  
  \node (F) [thebox, on chain=3,] % right=0.4 of E
       {\nodepart[]{one} 8000 \nodepart[]{two} 0000};
       
  \node (G) [thebox, on chain=2, below right=1.3cm and -1.5cm of B]
        {\nodepart[]{one} 3422 \nodepart[]{two} };
  
  \node (H) [thebox, on chain=2,] %at (4.5, -0.5) % right=0.4cm of G
       {\nodepart[]{one} \nodepart[]{two} };
  
  \node (I) [thebox, on chain=4, below right=0.3cm and -1.3cm of H]
        {\nodepart[]{one} 4000 \nodepart[]{two}};
  
  \node (J) [thebox, on chain=2,] % right=0.4cm of H 
        {\nodepart[]{one} 5321 \nodepart[]{two} 0000};
        
  \node (K) [thebox, on chain=4,] % right=0.4cm of I
       {\nodepart[]{one} 7222 \nodepart[]{two} 0000};


   \draw[arr] ($(A.one split)!0.5!(A.east)$) -- (B.west);
   \draw[arr] ($(B.west)!0.10!(B.east)$) |- (G.west);
   \draw[arr] ($(B.one split)!0.5!(B.east)$) -- (C.west);
   \draw[arr] ($(C.one split)!0.5!(C.east)$) -- (D.west);
   \draw[arr] ($(D.west)!0.10!(D.east)$) |- (E.west);
   \draw[arr] ($(E.one split)!0.5!(E.east)$) -- (F.west);
   \draw[arr] ($(G.one split)!0.5!(G.east)$) -- (H.west);
   \draw[arr] ($(H.west)!0.10!(H.east)$) |- (I.west);
   \draw[arr] ($(H.one split)!0.5!(H.east)$) -- (J.west);
   \draw[arr] ($(I.one split)!0.5!(I.east)$) -- (K.west);
\end{tikzpicture}
\end{document}

在此处输入图片描述


要参数化节点部分的文本,理论上你可以添加选项execute at begin nodeexecute at end node样式every <part name> node part,例如

every one node part/.style={
  execute at begin node=...,
  execute at end node=...
}

但目前有一个错误,execute at end node第一个节点部分执行了两次,请参阅https://github.com/pgf-tikz/pgf/issues/1155

相关内容