Установка длины с помощью ключа для узла TikZ

Установка длины с помощью ключа для узла TikZ

Я хотел бы создать несколько разделенных прямоугольников, ширина которых определяется длиной обозначенной линии. Я хотел бы сделать это через ключ, например:

\documentclass[border=4pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\newlength\aetmplength

\begin{document}

\begin{tikzpicture}[
  set text to width of/.code={%%
    \settowidth\aetmplength{#1}%%
    \typeout{--->`#1`::\the\aetmplength}%%
    \pgfkeysalso{text width=\the\aetmplength}%%
  },
  ]
  \node[draw,
        shape=rectangle split,
        rectangle split parts=2,
        set text to width of=This is the top of the node,
        %text width=0.95in
        ] () 
        {
         This is the top of the node
         \nodepart{two}
           first item\\
           second item\\
           \ldots};
\end{tikzpicture}

\end{document}

Но это не работает. Я мог бы легко потратить некоторое время, работая над этим. Так что это не проблема того, как задать нужную мне длину. Я хочу понять, почему это определение для ключа не делает то, что я хочу.

решение1

Объяснение, которое использует TikZ, \nullfontуже дано в percusseотвечать. Поэтому \settowidthне будет работать так, как ожидалось.

\pgfmathsetlength{width("#1")}

Вместо \settowidthфункции pgfmathможно widthиспользовать:

\pgfmathsetlength\aetmplength{width("#1")}

Полный пример:

\documentclass[border=4pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\newlength\aetmplength

\begin{document}

\begin{tikzpicture}[
  set text to width of/.code={%%
    % \settowidth\aetmplength{#1}%%
    \pgfmathsetlength\aetmplength{width("#1")}%
    \typeout{--->`#1`::\the\aetmplength}%%
    \pgfkeysalso{text width=\the\aetmplength}%%
  },
  ] 
  \node[draw,
        shape=rectangle split,
        rectangle split parts=2,
        set text to width of=This is the top of the node,
        %text width=0.95in
        ] ()
        {   
         This is the top of the node
         \nodepart{two}
           first item\\
           second item\\
           \ldots};
\end{tikzpicture}

\end{document}

Результат

\pgftext{...}

Другой способ — \pgftext, который возвращает в TeX, где \settowidthснова сработает. Поскольку аргумент \pgftextобрабатывается внутри группы, \aetmplengthон назначается глобально и \setwidthдействует на локальный временный регистр размерности. Локальные и глобальные назначения не следует смешивать в одной и той же управляющей последовательности по соображениям памяти.

\pgftext{%
  \settowidth{\dimen0}{#1}%%
  \global\aetmplength=\dimen0\relax
}%

node font

Последняя версия также может использоваться для учета значения option node font. Значение хранится в макросе \tikz@node@textfont. Без \makeatletterand \makeatotherпоследовательность управления также может быть указана с помощью \csnameand \endcsname:

\documentclass[border=4pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\newlength\aetmplength

\begin{document}

\begin{tikzpicture}[node font=\tiny,
  set text to width of/.code={%%
    \pgftext{%
      \csname tikz@node@textfont\endcsname
      \settowidth{\dimen0}{#1}%%
      \global\aetmplength=\dimen0\relax
    }%
    \typeout{--->`#1`::\the\aetmplength}%%
    \pgfkeysalso{text width=\the\aetmplength}%%
  },
  ] 
  \node[draw,
        shape=rectangle split,
        rectangle split parts=2,
        set text to width of=This is the top of the node,
        %text width=0.95in
        ] ()
        {   
         This is the top of the node
         \nodepart{two}
           first item\\
           second item\\
           \ldots};
\end{tikzpicture}

\end{document}

Результат с настройкой шрифта узла

решение2

Дизайн TikZ/PGF реализован таким образом, что его обычный синтаксис не допускает никаких ложных утечек пробелов или вывода непреднамеренных символов внутри кода и т. д. Один из способов сделать это — сопоставить текущий шрифт со специальным примитивом \nullfont.

Это приводит к тому, что вы не можете просто управлять шириной текста без воссоздания исходного не- \nullfontсостояния. Просто чтобы дать некоторый контекст, ниже приведено определение pgf@pictureсреды begin:

    \begingroup%
      \let\pgf@setlengthorig=\setlength%
      \let\pgf@addtolengthorig=\addtolength%
      \let\pgf@selectfontorig=\selectfont%  <== Records the original
      \let\setlength=\pgf@setlength%
      \let\addtolength=\pgf@addtolength%
      \let\selectfont=\pgf@selectfont% <== Overwrites
      \nullfont\spaceskip0pt\xspaceskip0pt% <== Resets font
      \setbox\pgf@layerbox@main\hbox to0pt\bgroup%
        \begingroup%

Как только мы это узнаем, можно временно вернуться к исходному определению внутри группы, получить ширину и выжить в группе.

\documentclass[border=4pt,tikz]{standalone}
\usetikzlibrary{shapes.multipart}
\makeatletter
\tikzset{set text to width of/.code={%%
\begingroup%
\pgfutil@selectfont%
\settowidth\pgf@xc{#1}% <== PGF internal scratch registers xa,ya,xb,yb,xc,yc
\edef\temp{\noexpand\pgfkeysalso{text width=\the\pgf@xc}}%<- Nonzero
\expandafter\endgroup\temp%%
\typeout{--->`#1`::\the\pgf@xc}%<-Still zero!
  }
}
\makeatother

\begin{document}
\begin{tikzpicture}
  \node[draw,
        align=center,%<- for line breaks
        shape=rectangle split,
        rectangle split parts=2,
        set text to width of=This is looooooooonnnnnnnnger than the top,
        ] () 
        {
         This is the top of the node
         \nodepart{two}
           first item\\
           second item\\
           \ldots};
\end{tikzpicture}
\end{document}

введите описание изображения здесь

Связанный контент