为什么下面的代码会给出这个错误信息?
错误
错误:未定义控制序列。
--- TeX 说 --- \pgfmath@dimen@ ...men@@ #1=0.0pt\relax \pgfmath@
l.28 \draw (\getWickersonLeft{c},0) -- (\getWickersonRight{c},5);
代码
\documentclass{article}
\usepackage{tikz}
\pgfkeys{/wickersons/.cd,
execute style/.style={#1},
execute macro/.style={execute style/.expand once=#1},
left/.code={\gdef\wickersonsleft{#1}},
right/.code={\gdef\wickersonsright{#1}}
}
\def\getWickersonLeft#1{\csname wickerson#1left\endcsname}
\def\getWickersonRight#1{\csname wickerson#1right\endcsname}
\newcommand*\defWickersonMacros[3]{%
\expandafter\edef\csname wickerson#1left\endcsname{#2}
\expandafter\edef\csname wickerson#1right\endcsname{#3}
}
\begin{document}
\begin{tikzpicture}[x=1mm,y=-1mm]%
\foreach \x/\xvalue in {c/{left=67,right=77}} {
\pgfkeys{/wickersons/.cd, execute macro=\xvalue}
\expandafter\defWickersonMacros{c}{\wickersonsleft}{\wickersonsright}
}
\draw (\getWickersonLeft{c},0) -- (\getWickersonRight{c},5);
\end{tikzpicture}
\end{document}
答案1
我宁愿使用\pgfkeysvalueof
定义事物的方式。这是一种非常复杂的方法,可以避免真正的力量,pgfkeys
因为你使用的是虚拟宏而不是键。考虑将所有选项发送给属于一个系列的某些键。
这里的问题是宏的参数在另一个定义中使用,因此#
字符应该加倍。
\documentclass{article}
\usepackage{tikz}
\pgfkeys{/wickersons/.cd,
execute style/.style={#1},
execute macro/.style={execute style/.expand once=#1},
left/.code={\xdef\wickersonsleft{#1}},
right/.code={\xdef\wickersonsright{#1}}
}
\edef\getWickersonLeft#1{\csname wickerson#1left\endcsname}
\edef\getWickersonRight#1{\csname wickerson#1right\endcsname}
\newcommand*\defWickersonMacros[3]{%
\expandafter\xdef\csname wickerson##1left\endcsname{#2}% Double ##
\expandafter\xdef\csname wickerson##1right\endcsname{#3}% Double ##
}
\begin{document}
\begin{tikzpicture}[x=1mm,y=-1mm]%
\foreach \x/\xvalue in {c/{left=67,right=77}} {
\pgfkeys{/wickersons/.cd, execute macro=\xvalue}
\defWickersonMacros{c}{\wickersonsleft}{\wickersonsright}
}
\draw (\getWickersonLeft{c},0) -- (\getWickersonRight{c},5);
\end{tikzpicture}
\end{document}
输出 :)
答案2
后敲击有已回答你的问题是,我想给你一个关于如何使用 PGF 键和 TikZ 的功能来处理你的列表的替代方法。
部分代码受到您最近提出的另一个问题的启发。
代码
\documentclass[tikz]{standalone}
\makeatletter
\pgfqkeys{/wickersons}{
add path/.code args={#1}{%
\begingroup% a group so the initial values don't need to be repeated but can be set in a scope above
\pgfqkeys{/wickersons/path vars}{#1}% set only the keys that are given in '#1', other wise the current value will be used (probably the .initial one)
% now expand everything (but the label which may contain unexpandable stuff, we only want to expand that once)
\edef\pgf@tempa{{\pgfkeysvalueof{/wickersons/path vars/name}/.style={insert path={%
(\pgfkeysvalueof{/wickersons/path vars/left},0) -- node [every wickersons label/.try] {\unexpanded\expandafter{\wickersons@pathvars@label}}
(\pgfkeysvalueof{/wickersons/path vars/right},5)}}}}%
% and get it out of this group
\pgfmath@smuggleone\pgf@tempa
\endgroup
% the 'path vars' now contain all there values before 'add path' was used
%
% have you seen the extra pair of braces in \pgf@tempa? Those where necessary, otherwise I had to use
% \expandafter\tikzset\expandafter{\pgf@tempa}
% here
\expandafter\tikzset\pgf@tempa
},
path vars/.cd,
name/.initial=path,% if 'add path' has been used without the 'name' key the style would have been named 'path'
left/.initial=0, % if 'add path' has been used without the 'left' key the left point would have started at (0,0)
right/.initial=0, % ...
label/.store in=\wickersons@pathvars@label,% or toks
label=% % ...
}
\makeatother
\begin{document}
\begin{tikzpicture}[
x=1mm,
y=-1mm,
->,
thick,
every wickersons label/.style={midway, above, sloped},
/wickersons/add path/.list={%
{name=foo, left= 2, right=23, label=horse},%
{name=bar, left=25, right=29, label=sheep},%
{name=baz, left=31, label=\textbf{zebra}}%
}]
\draw [every wickersons label/.append style={pos=.2}] [foo];
\draw [bar];
\draw [every wickersons label/.append style={pos=.4}] [baz]; % uses right=0
\end{tikzpicture}
\end{document}