使用 foreach 向 TikZ 节点内的字节字段添加可变数量的行?(第 2 部分)

使用 foreach 向 TikZ 节点内的字节字段添加可变数量的行?(第 2 部分)

我正在尝试在 TikZ 节点内向字节字段添加可变数量的字段。之前的一个问题(使用 foreach 向 TikZ 节点内的字节字段添加可变数量的行?) 给出了有用的提示,但我仍然无法让它工作。所以,这里有一个更详细的例子。

\documentclass[tikz]{standalone}

\usepackage{bytefield}

\usetikzlibrary{positioning}

\begin{document}

% What I want to achieve, written out without loops:
% (inelegant, does not scale to the large number of nodes
% for which I need this)
\begin{tikzpicture}

  \node [draw] (a) {a};
  \node [draw] at (6,0) (b) {b};
  
  \node [below=of a] {
    \begin{bytefield}{8}
      \wordbox{1}{Source: b} 
      \\ \wordbox{1}{1} 
      \\ \wordbox{1}{2} 
      \\ \wordbox{1}{3}
    \end{bytefield}
  };

  \node [below=of b] {
    \begin{bytefield}{8}
      \wordbox{1}{Source: a} 
      \\ \wordbox{1}{4} 
      \\ \wordbox{1}{5}
    \end{bytefield}
  };
\end{tikzpicture}

% What should be a step in the right direction,
% compare https://tex.stackexchange.com/questions/679919/using-foreach-to-add-variable-number-of-rows-to-a-bytefield-inside-a-tikz-node/679923?noredirect=1#comment1687472_679923

\begin{tikzpicture}[wordbox/.code={\\\wordbox{1}{#1}}]
  \node {
    \begin{bytefield}{8}
      \wordbox{1}{Source: A} 
      \tikzset{wordbox/.list={1,2,3}}
    \end{bytefield}
  };
\end{tikzpicture}



% How I hope to get it to work, but only get two wordboxes,
% instead of four on the left, three on the right: 
\begin{tikzpicture}[wordbox/.code={\\\wordbox{1}{#1}}]

  \node [draw] (a) {a};
  \node [draw] at (6,0) (b) {b};
  
  \foreach \n/\fields in {a/{1,2,3},b/{4,5}} {
  \node [below=of \n] {
    \begin{bytefield}{8}
      \wordbox{1}{Source: \n}
      \tikzset{wordbox/.list=\fields}
    \end{bytefield}
  };
  }
\end{tikzpicture}


% An alternative with a foreach inside bytefield does not even compile: 
% \begin{tikzpicture}

%   \node [draw] (a) {a};
%   \node [draw] at (6,0) (b) {b};
  
%   \foreach \n/\fields in {a/{1,2,3},b/{4,5}} {
%   \node [below=of \n] {
%     \begin{bytefield}{8}
%       \wordbox{1}{Source: \n}
%       \foreach \f in \fields { \\ \wordbox{1}{\f} }
%     \end{bytefield}
%   };
%   }
% \end{tikzpicture}


\end{document}

这三个步骤的示例图如下所示。

在最后一种情况下,列表处理程序似乎没有遍历字段?有什么办法可以解决这个问题吗?

我想要的是:

我想要的是

朝着正确方向迈出的中间一步?

朝着正确方向迈出的中间一步?

我得到的是:

我得到了什么

答案1

如果你只是说/.list=\fields,那么宏\fields将是列表中的唯一元素。在内部,这将导致一个循环,如下所示

\foreach \ELEMENT in {\fields}

在处理程序评估它之前,你需要\fields至少扩展一次。因此,你需要.list

\tikzset{wordbox/.list/.expand once=\fields}

或者

\tikzset{wordbox/.list/.expanded=\fields}

您的第二个示例(带有显式\foreach循环)会导致问题,因为它将对每次迭代进行分组。它类似于

\begin{bytefield}{8}
  \wordbox{1}{Source: \n}
  { \\ \wordbox{1}{1} }
  { \\ \wordbox{1}{2} }
  { \\ \wordbox{1}{3} }
\end{bytefield}

这与bytefield内部运作方式相冲突。

如果您不满意.list(内部使用 PGFFor\foreach并允许...语法),您可以使用例如\int_step_inline:nnn这样的用法:

% Preamble
\ExplSyntaxOn
\DeclareDocumentCommand{\ForeachInline}{}{\int_step_inline:nnn}
\ExplSyntaxOff

% Document
\begin{tikzpicture}
\node [draw] (a) {a};
\node [draw] at (6,0) (b) {b};

\foreach \n/\st/\en in {a/1/3, b/4/5} {
  \node [below=of \n] {
    \begin{bytefield}{8}
      \wordbox{1}{Source: \n}
      \ForeachInline{\st}{\en}{ \\ \wordbox{1}{##1} }
    \end{bytefield}
  };
}
\end{tikzpicture}

相关内容