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関数の代わりに次の関数pgfmathwidth使うこともできます:

\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{...}

もう 1 つの方法は で\pgftext、これは TeX に戻り、ここで が\settowidth再び機能します。 の引数は\pgftextグループ内で処理されるため、\aetmplengthはグローバルに割り当てられ、\setwidthローカルの一時次元レジスタに作用します。メモリ上の理由から、ローカル割り当てとグローバル割り当てを同じ制御シーケンスで混在させないでください。

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

node font

最新バージョンは、オプション の値を尊重するためにも使用できますnode font。値はマクロ に格納されます\tikz@node@textfont。 と がない場合\makeatletter\makeatother制御シーケンスは と によっても指定でき\csnameます\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 の設計は、通常の構文に不要な空白の漏れが生じたり、コード内に意図しない文字が出力されたりしないように行われます。その方法の 1 つは、現在のフォントを特殊なプリミティブにマップすることです\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}

ここに画像の説明を入力してください

関連情報