以下最小工作示例显示了问题。 mainmacro 是我需要的示例;在这里我想使用我的键和来自 tikz 的键(如 draw、color、shape)。只有使用 . 时结果才正常。 是不够的shape = circle
。circle
如果我想要红色,则同上。color = red
是强制性的。 我的代码有什么问题? 您知道实现我想要的更好的方法吗?
\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\pgfkeys{/mykeys/.cd,
d/.code = {\def\macro@d{#1}},
a/.code = {\def\macro@a{#1}},
/mykeys/.unknown/.code = {\let\searchname=\pgfkeyscurrentname
\pgfkeysalso{\searchname/.try=#1,
/tikz/\searchname/.retry=#1}
}
}
\def\mainmacro{\pgfutil@ifnextchar[{\main@macro}{\main@macro[]}}
\def\main@macro[#1](#2)#3{%
\begingroup
\pgfkeys{mykeys/.cd,
d = 1,
a = 45}
\pgfqkeys{/mykeys}{#1}
\path (#2) --+(\macro@a:\macro@d) node[/mykeys/.cd,#1] {#3};
\endgroup
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw (0,0) --( 1,1) coordinate (a) ;
\mainmacro[a=0,d=12pt,draw,shape=circle](a){label 1}
\mainmacro[d=2cm,draw,circle](a){label 2}
\end{tikzpicture}
\end{document}
更新
\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\pgfkeys{/mykeys/.cd,
d/.store in = {\macro@d},
a/.store in = {\macro@a},
/mykeys/.unknown/.code = {\let\searchname=\pgfkeyscurrentname
\pgfkeysalso{\searchname/.try=#1,
/tikz/\searchname/.retry=#1,
/tikz/.cd,#1}}}
\def\mainmacro{\pgfutil@ifnextchar[{\main@macro}{\main@macro[]}}
\def\main@macro[#1](#2){%
\begingroup
\pgfkeys{mykeys/.cd,
d = 1,
a = 1}
\pgfqkeys{/mykeys}{#1}
\draw[/mykeys/.cd,#1] (\macro@a,\macro@a) circle (\macro@d) --++(1,1) node[#1] {label};%
\endgroup
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (5,0) ;
\mainmacro[red,ultra thick](a)
\end{tikzpicture}
\end{document}
这个技巧对节点有效,但对节点无效,\draw
也许我的代码中某处是错的
答案1
发生这种情况是因为形状、颜色名称(和一些其他内容)不是键。换句话说,当您写入red
或diamond
时,它没有针对此类内容的专用键。因此,它会通过 TikZ 机制,searchname/.retry
但由于没有这样的键,它会失败。相反,/tikz/.unknown/.code
它更加全面和复杂。例如
{%
% Ok, second chance: This might be an arrow specification:
\expandafter\pgfutil@in@\expandafter-\expandafter{\tikz@key}%
\ifpgfutil@in@%
% Ah, an arrow spec!
\expandafter\tikz@processarrows\expandafter{\tikz@key}%
\else%
% Ok, third chance: A shape!
\expandafter\ifx\csname pgf@sh@s@\tikz@key\endcsname\relax%
\pgfkeys{/errors/unknown key/.expand
once=\expandafter{\expandafter/\expandafter t\expandafter
i\expandafter k\expandafter z\expandafter/\tikz@key}{##1}}%
\else%
\edef\tikz@shape{\tikz@key}%
\fi%
\fi%
}%
我想到两种方法来做到这一点:
您可以在密钥试验结束时明确传递给 TikZ,让它决定要做什么。因此,您添加以下内容
\pgfkeys{/mykeys/.cd, d/.store in = {\macro@d}, a/.store in = {\macro@a}, /mykeys/.unknown/.code = {\let\searchname=\pgfkeyscurrentname% \pgfkeysalso{\searchname/.try=#1, /tikz/\searchname/.retry=#1, /tikz/.cd,#1}% <--- Now invoked under TikZ } }
这里,我们明确触发 TikZ 未知机制,因为现在该系列是 TikZ。因此会进行所有形状名称检查等等。
编写自己的
/.unknown/.code
处理程序来处理已知名称。例如使 PGFkeys 路径在整个范围内优先于其他路径有几个例子。
答案2
这里有两个简单的解决方案。
第一个解决方案(更好?)
您可以使用/.search also
处理程序(参见 pgfmanual v3.0.1a 的第 891 页):
\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\pgfkeys{
/mykeys/.cd,
d/.code = {\def\macro@d{#1}},
a/.code = {\def\macro@a{#1}},
/mykeys/.search also={/tikz},
}
\def\mainmacro{\pgfutil@ifnextchar[{\main@macro}{\main@macro[]}}
\def\main@macro[#1](#2)#3{%
\begingroup
\pgfkeys{mykeys/.cd,
d = 1,
a = 45}
\pgfqkeys{/mykeys}{#1}
\path (#2) --+(\macro@a:\macro@d) node[/mykeys/.cd,#1] {#3};
\endgroup
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw (0,0) --( 1,1) coordinate (a) ;
\mainmacro[a=0,d=12pt,draw,red,shape=circle](a){label 1}
\mainmacro[d=2cm,draw,circle](a){label 2}
\end{tikzpicture}
\end{document}
第二种解决方案
您可以使用/.forward to
处理程序(参见 pgfmanual v3.0.1a 的第 890 页):
\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\pgfkeys{
/mykeys/.cd,
d/.code = {\def\macro@d{#1}},
a/.code = {\def\macro@a{#1}},
/mykeys/.unknown/.forward to=/tikz/\pgfkeyscurrentname,
}
\def\mainmacro{\pgfutil@ifnextchar[{\main@macro}{\main@macro[]}}
\def\main@macro[#1](#2)#3{%
\begingroup
\pgfkeys{mykeys/.cd,
d = 1,
a = 45}
\pgfqkeys{/mykeys}{#1}
\path (#2) --+(\macro@a:\macro@d) node[/mykeys/.cd,#1] {#3};
\endgroup
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw (0,0) --( 1,1) coordinate (a) ;
\mainmacro[a=0,d=12pt,draw,red,shape=circle](a){label 1}
\mainmacro[d=2cm,draw,circle](a){label 2}
\end{tikzpicture}
\end{document}