![命令的评估会改变其价值吗?](https://linux22.com/image/467409/%E5%91%BD%E4%BB%A4%E7%9A%84%E8%AF%84%E4%BC%B0%E4%BC%9A%E6%94%B9%E5%8F%98%E5%85%B6%E4%BB%B7%E5%80%BC%E5%90%97%EF%BC%9F.png)
我正在尝试使用 pgf-umlcd 创建 UML 类图,但遇到了问题。最终,我想使用指定的水平间距。我还需要能够设置文本宽度。
我希望能够处理不同的锚点。我的计算应该没问题,但是命令似乎被评估为不同的值。
我创建了一个包含两个类的示例。一个类使用“变量”,另一个类使用其值。
重现代码:
\documentclass{article}
\usepackage[a4paper]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usepackage{pgf-umlcd}
\begin{document}
\begin{tikzpicture}[font=\small,outer frame sep=0,outer sep=0]
\newcommand{\currTextWidth}{7.5cm}
\newcommand{\desiredSpacing}{0cm}
\newcommand{\pad}{\the\dimexpr \pgfkeysvalueof{/pgf/inner xsep}*2\relax} % calculate padding
\newcommand{\overAllWidth}{\the\dimexpr \currTextWidth + (\pad)\relax}
\newcommand{\currSpacing}{\the\dimexpr \desiredSpacing + \overAllWidth / 2\relax}
% this resembles the referenced class
\begin{class}[text width=\currTextWidth]{RandomClass}{0,0}
\operation[0]{+ doSomething(): void}
\end{class}
% calculated values
\node at (0,1.5) {overAllWidth = \overAllWidth};
\node at (0,1) {currSpacing = \currSpacing};
% this result would be fine
\begin{class}[text width=\currTextWidth,right=109.78008pt]{ClassUsingValue}{RandomClass.north}
\end{class}
% but I want to use the 'variable' here
\begin{class}[text width=\currTextWidth,right=\currSpacing]{ClassUsingVariable}{RandomClass.south}
\end{class}
\end{tikzpicture}
\end{document}
输出:
答案1
至少对我来说,在这里使用\newcommand
而不是 并没有多大意义。为什么不使用 LaTeX 长度,而要将 LaTeX 宏转换为尺寸?\newlength
\documentclass{article}
\usepackage[a4paper]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usepackage{pgf-umlcd,calc}
\newlength\desiredSpacing
\newlength\currTextWidth
\newlength\pad
\newlength\overAllWidth
\newlength\currSpacing
\begin{document}
\begin{tikzpicture}[font=\small,outer frame sep=0,outer sep=0]
\setlength\desiredSpacing{0cm}
\setlength\currTextWidth{7.5cm}
\setlength\pad{\pgfkeysvalueof{/pgf/inner xsep}*2}
\setlength\overAllWidth{\currTextWidth + \pad}
\setlength\currSpacing{\desiredSpacing + \overAllWidth / 2}
% this resembles the referenced class
\begin{class}[text width=\currTextWidth]{RandomClass}{0,0}
\operation[0]{+ doSomething(): void}
\end{class}
% calculated values
\node at (0,1.5) {overAllWidth = \the\overAllWidth};
\node at (0,1) {currSpacing = \the\currSpacing};
% this result would be fine
\begin{class}[text width=\currTextWidth,right=109.78008pt]{ClassUsingValue}{RandomClass.north}
\end{class}
% but I want to use the 'variable' here
\begin{class}[text width=\currTextWidth,right=\currSpacing]{ClassUsingVariable}{RandomClass.south}
\end{class}
\end{tikzpicture}
\end{document}
答案2
问题是,当你在里面时,class
的值inner xsep
为零,但是当你在中排版文本时情况就不同了\node
。
如果我添加
\showthe\dimexpr\pgfkeysvalueof{/pgf/inner xsep}\relax
在class
环境中,我得到了0.0pt
,但是当我将它添加到节点内部时,我得到了3.08224pt
。
如果要冻结 的值inner xsep
,则需要\edef
而不是\newcommand
(与 相同\def
)。
\documentclass{article}
\usepackage{tikz}
\usepackage{pgf-umlcd}
\begin{document}
\begin{tikzpicture}[font=\small,outer frame sep=0,outer sep=0]
\def\currTextWidth{7.5cm}
\def\desiredSpacing{0cm}
\edef\pad{\the\dimexpr \pgfkeysvalueof{/pgf/inner xsep}*2\relax} % calculate padding
\edef\overAllWidth{\the\dimexpr \currTextWidth + (\pad)\relax}
\edef\currSpacing{\the\dimexpr \desiredSpacing + \overAllWidth / 2\relax}
% this resembles the referenced class
\begin{class}[text width=\currTextWidth]{RandomClass}{0,0}
\operation[0]{+ doSomething(): void}
\end{class}
% calculated values
\node at (0,1.5) {overAllWidth = \overAllWidth};
\node at (0,1) {currSpacing = \currSpacing};
% this result would be fine
\begin{class}[text width=\currTextWidth,right=106.69783pt]{ClassUsingValue}{RandomClass.north}
\end{class}
% but I want to use the 'variable' here
\begin{class}[text width=\currTextWidth,right=\currSpacing]{ClassUsingVariable}{RandomClass.south}
\end{class}
\end{tikzpicture}
\end{document}
在命名此类命令时要小心,因为\def
和\edef
会默默地(本地)改变现有命令的含义。
但为了安全起见,您仍然可以使用\newcommand
:
\begin{tikzpicture}[font=\small,outer frame sep=0,outer sep=0]
\newcommand{\currTextWidth}{7.5cm}
\newcommand{\desiredSpacing}{0cm}
\ExpandArgs{ne}\newcommand{\pad}{\the\dimexpr \pgfkeysvalueof{/pgf/inner xsep}*2\relax}
\ExpandArgs{ne}\newcommand{\overAllWidth}{\the\dimexpr \currTextWidth + (\pad)\relax}
\ExpandArgs{ne}\newcommand{\currSpacing}{\the\dimexpr \desiredSpacing + \overAllWidth / 2\relax}
% this resembles the referenced class
[...]
因为\ExpandArgs
默认跳过其参数后面的标记;ne
我们指示对后面的第一个大括号组不执行任何操作,并完全展开后面的第二个大括号组的内容。