我正在尝试将一些参数传递给节点样式,并找到了简单情况的答案:是否可以在节点声明中的三个参数中考虑一个可选参数?
但是,我无法将其作为更复杂结构的一部分来实现。这些参数存储在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
所以没有办法通过小幅调整代码来使其工作。有多种方法可以使您的代码工作,而正确的方法则取决于您想要通过此方法实现什么。
我认为最简单的方法是定义颜色别名。你必须在某个时候决定是Tom
和red
是Jane
,blue
那么为什么不简单地为颜色设置别名呢?它所需要的只是:
\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}