TikZ 节点参数和 pgfkeys

TikZ 节点参数和 pgfkeys

我正在尝试将一些参数传递给节点样式,并找到了简单情况的答案:是否可以在节点声明中的三个参数中考虑一个可选参数?

但是,我无法将其作为更复杂结构的一部分来实现。这些参数存储在pgfkeys命名的命令中,并且必须\ColorEdges在发送到节点之前传递该命令(此特定键在其他地方多次使用)。

在下面的 MWE 中,它部分起作用:我可以打印节点标签,表示“Tom”为“蓝色”,表示“Jane”为“红色”。同样的机制无法选择颜色draw(取消注释该行draw=\expandafter\ColorEdges\expandafter{\peoplecolor},以查看问题)。

有人知道为什么吗?

平均能量损失

\documentclass[border=5pt]{standalone}
\usepackage{tikz}
\usepackage{etoolbox}

\begin{document}
    
    % Define several keys for each person
    \pgfkeys{/gtr/database/.cd,
        persdata/.is choice,
        persdata/TomID/.style={
            name            = {Tom Surname},
            people color    = {Tom}
        }
    }

    \pgfkeys{/gtr/database/.cd,
        persdata/.is choice,
        persdata/JaneID/.style={
            name            = {Jane Anothersurname},
            people color    = {Jane}
        }
    }

    % Define new keys in database
    \pgfkeys{/gtr/database/.cd,
        name/.store in=\usualname,
        people color/.store in=\peoplecolor
    }

    % Associate color based on people color
    \newcommand{\ColorEdges}[1]{
        \ifstrequal{#1}{Tom}{blue}{%
            \ifstrequal{#1}{Jane}{red}{%
        }}
    }

    % Define command to print people data
    \newcommand\PrintPeople[1]{
        
        % Locate appropriate keys set     
        \pgfkeys{/gtr/database/.cd,persdata=#1}%
        
            \begin{tikzpicture}[
                peoplebox/.style={
                    very thick,
                    fill=blue!40}
                ]
                
                \node [peoplebox,
%               draw=\expandafter\ColorEdges\expandafter{\peoplecolor},
                label=\expandafter\ColorEdges\expandafter{\peoplecolor}] {
                    \ifdefined\usualname
                    \usualname
                    \fi
                };      
                
            \end{tikzpicture}
    }

    \PrintPeople{TomID}
    
    \PrintPeople{JaneID}
    
\end{document}

答案1

问题是你的条件,\ifstrequal不是可扩展。它在命令中有效,label因为它排版了结果,因此在 TeX 的“胃”中处理。它在命令中不起作用,draw因为它试图扩展结果并在其他命令中使用它,因此在非可扩展标记上失败。

您可以通过输入以下内容来看到这一点:

\edef\exptest{\ColorEdges{Tom}}
\show\exptest

所以没有办法通过小幅调整代码来使其工作。有多种方法可以使您的代码工作,而正确的方法则取决于您想要通过此方法实现什么。

我认为最简单的方法是定义颜色别名。你必须在某个时候决定是TomredJaneblue那么为什么不简单地为颜色设置别名呢?它所需要的只是:

\colorlet{Tom}{red}
\colorlet{Jane}{blue}

这比您的代码有一个优势,因为它非常易于维护,并且可以向列表中添加额外的名称/颜色(使用嵌套条件,您将得到一大堆括号)。它将所有颜色定义保存在一个地方(这就是为什么我假设您没有将它们放在数据中),并且非常易于使用 - 只需在您要放置颜色的任何地方使用别名即可。

如果您确实想要一个与现有条件类似的条件,那么您可以在此处使用 LaTeX3 代码。这提供了可扩展的字符串比较。它还有一个好处,就是它可以根据要求扩展其参数,因此您可以定义:

\usepackage{expl3}
\ExplSyntaxOn
\newcommand{\ColorEdges}[1]{
  \str_if_eq:eeTF {#1}{Tom}{blue}
  {
    \str_if_eq:eeTF {#1}{Jane}{red}
    {
    }
  }
}
\ExplSyntaxOff

这样就可以draw=\ColorEdges{\peoplecolor}按原样工作。

如果您想自己控制扩展(在调用阶段),那么使用 pgfkeys 的一个巧妙技巧是定义一个执行实际颜色设置的包装器键,然后.expand once在其上使用处理程序。

因此\ColorEdges定义为:

\usepackage{expl3}
\ExplSyntaxOn
\newcommand{\ColorEdges}[1]{
  \str_if_eq:nnTF {#1}{Tom}{blue}
  {
    \str_if_eq:nnTF {#1}{Jane}{red}
    {
    }
  }
}
\ExplSyntaxOff

因此没有自动扩展其参数然后定义:

\tikzset{
  set draw color/.style={
    draw=\ColorEdges{#1}
  }
}

并通过以下方式调用它:

set draw color/.expand once=\peoplecolor

答案2

我发现了一个可怕丑陋的解决方案。唯一值得称赞的是它确实有效。

\ColorEdges我重新定义了要打印的命令\node [],包括我想要调整的参数。然后我调用它并在其后跟上{my node content}。请注意,peoplebox节点类型仍然可以在环境内部定义tikzpicture,并在通过命令使用时加以考虑\ColorEdges

MWE 如下,但我会欢迎任何比这个更清晰的答案:)

平均能量损失

\documentclass[border=5pt]{standalone}
\usepackage{tikz}
\usepackage{etoolbox}

\begin{document}
    
    % Define several keys for each person
    \pgfkeys{/gtr/database/.cd,
        persdata/.is choice,
        persdata/TomID/.style={
            name            = {Tom Surname},
            people color    = {Tom}
        }
    }

    \pgfkeys{/gtr/database/.cd,
        persdata/.is choice,
        persdata/JaneID/.style={
            name            = {Jane Anothersurname},
            people color    = {Jane}
        }
    }

    % Define new keys in database
    \pgfkeys{/gtr/database/.cd,
        name/.store in=\usualname,
        people color/.store in=\peoplecolor
    }

    % Associate color based on people color
    \newcommand{\ColorEdges}[1]{
        \ifstrequal{#1}{Tom}{\node [peoplebox, draw=blue]}{%
            \ifstrequal{#1}{Jane}{\node [peoplebox, draw=red]}{%
        }}
    }

    % Define command to print people complete data in English
    \newcommand\PrintPeople[1]{
        
        % Locate appropriate keys set     
        \pgfkeys{/gtr/database/.cd,persdata=#1}%
        
            \begin{tikzpicture}[
                peoplebox/.style={
                    very thick,
                    fill=blue!20}
                ]
                
                \expandafter\ColorEdges\expandafter{\peoplecolor}{
                    \ifdefined\usualname
                    \usualname
                    \fi
                };
                
            \end{tikzpicture}
    }

    \PrintPeople{TomID}
    
    \PrintPeople{JaneID}
    
\end{document}

相关内容