代码

代码

这是一个后续问题在样式中添加节点

如果我使用以下代码,我会得到一个奇怪的行为:

代码

\documentclass[tikz]{standalone}
\usetikzlibrary{matrix,fit,backgrounds}
\tikzset{
  fill first cell/.style={
    append after command={
      \pgfextra
        \pgfonlayer{background}
          \tikzset{every node/.style=}
          \node[fit=(\tikzlastnode-\the\pgfmatrixcurrentcolumn-\the\pgfmatrixcurrentrow), inner sep=+0pt, fill=#1] {};
        \endpgfonlayer
      \endpgfextra
    }
  },
  fill first cell/.default=red!7
}
\begin{document}
\begin{tikzpicture}
\matrix (m) [matrix of nodes, fill first cell] {
  1 & 2 \\
  3 & 4 \\
};
\end{tikzpicture}
\end{document}

输出

输出

期望输出

期望输出

打印时一切看起来都符合预期。但是,PDF 查看器显示的所有字母都略微加粗。此行为可在上面显示的两个输出中看到。我强烈怀疑矩阵的内容被绘制了两次。

我知道它至少被画过一次来自我风格的代码。为了证明这一点,删除背景层命令,红色矩形仍会出现在数字 4 的背景中。

此外,如果我使用 pgfnode 而不是 Tikz 节点,则问题不会出现。

是什么导致了这种现象?我该如何解决?

编辑

在@percusse、@DavidCarlisle 和@AndrewSwann 的帮助下,我能够找到更短的 MWE 以及更好的方法来检查错误是否存在。

以下代码展示了这个错误:

\documentclass[tikz]{standalone}
\begin{document}
\showoutput
\begin{tikzpicture}
\path node {x}
      \pgfextra
        \node{};
      \endpgfextra
;
\end{tikzpicture}
\end{document}

通过使用以下命令,pdflatex mwe.tex | grep cmr/ | wc -l您可以检查字符x被打印了多少次。1表示没有错误,2表示有错误。

通过玩弄内容,\pgfextra ... \endpgfextra我得出了一些额外的观察:

  • \pgfnode{rectangle}{node}{}{}{}没有表现出错误,所以这似乎是 Tikz 的问题
  • \draw (0,0) -- (0,1) -- (1,1) -- (1,0) -- cycle;也没有出现错误
  • \draw (0,0) -- (0,1) -- (1,1) -- (1,0) -- cycle node {};确实存在错误
  • \draw (0,0) -- (0,1) -- (1,1) -- (1,0) -- cycle; \node {};没有出现错误

组成路径的线似乎没有被绘制两次。然而,在下面的代码中,两个节点 x 和 y 都被打印了两次。

\documentclass[tikz]{standalone}
\begin{document}
\showoutput
\begin{tikzpicture}
\path node {x} node {y}
      \pgfextra
        \node{};
      \endpgfextra
;
\end{tikzpicture}
\end{document}

解决方法(已过时,请参阅解决方案)

这个问题还没有答案,但是现在有一个可用的解决方法:只需在里面\path;之前添加一个。\node{};\pgfextra

解决方案

正如所提到的在样式中添加节点在@MarkWibrow的回答中,问题在于缺乏对外部路径的保护\pgfextra。保护的经典方法是使用\pgfinterruptpath。然而,这是插入 TikZ 节点时不够并且必须与 相结合\setbox\tikz@figbox=\box\pgfutil@voidb@x。固定的 MWE 如下所示:

\documentclass[tikz]{standalone}
\begin{document}
\showoutput
\begin{tikzpicture}
\path node {x}
      \pgfextra
        \pgfinterruptpath
          \makeatletter\setbox\tikz@figbox=\box\pgfutil@voidb@x\makeatother
          \node{};
        \endpgfinterruptpath
      \endpgfextra
;
\end{tikzpicture}
\end{document}

\pgfinterrupath两个目的。如果我们在节点顶部x绘制路径,它将确保该节点y不会删除它。在我们的例子中,它是为了\makeatletter\setbox\tikz@figbox=\box\pgfutil@voidb@x\makeatother不丢弃x节点而需要的。

此解决方案适用于 TikZ/PGF 版本 2.10 和 CVS 版本。@MarkWibrow 在 CVS 版本中提到的问题如下:遇到拟合节点时,矩阵的节点全部插入到背景层,而不是它们所属的主层。这是一个错误(http://sourceforge.net/p/pgf/bugs/260/) 现已修复。如果仅使用 CVS 版本(2013 年 9 月 9 日之后),则以下代码有效:

\documentclass[tikz]{standalone}
\begin{document}
\showoutput
\begin{tikzpicture}
\path node {x}
      \pgfextra
        \pgfinterruptpath
          \node{};
        \endpgfinterruptpath
      \endpgfextra
;
\end{tikzpicture}
\end{document}

答案1

路径上的所有节点都放置在一个称为 的特殊框中\tikz@figbox。当对节点执行某些操作时,在某个时刻会发生类似以下的情况:

\setbox\tikz@figbox=\hbox\bgroup%
   \setbox\pgfutil@tempboxa=\copy\tikz@figbox%
   \unhbox\pgfutil@tempboxa%
   %
   % Code inserting/positioning node content
   %
\egroup%

在路径的末端,盒子被使用并且变为空(这就是插入\path;似乎有效的原因)。

在上述情况下,OP在另一条路径(a是一种节点类型,因此是一种路径)内开始一条路径(a\node是一种特殊的路径 -\path自动插入) 。\matrix

由于\tikz@figbox矩阵中的内容在\node命令之前不会被清空,因此矩阵内容也会插入到节点内容的框中。可以将其放在节点\setbox\tikz@figbox=\box\pgfutil@voidb@x命令之前,以查看是否解决了该问题。

实际上 OP 所做的 (或多或少) 是这样的:

\newbox\mybox
\setbox\mybox=\hbox{matrix}
{\setbox\mybox=\hbox{\copy\mybox\space node}1. \box\mybox}
2. \box\mybox

产生

1. matrix node 2. matrix

我个人并不认为这是一个错误,OP 给出的方法并不是一个好方法。\pgfextra如果使用其他路径/图片(例如,使用),则必须小心使用\pgfinterruptpath \endpgfinterruptpath。尽管在这种情况下它不能解决问题。

无论哪种方式,最新的 CVS 版本都不会发生重复,但密钥也不会append after command产生所需的效果。

答案2

矩阵被绘制了两次,这是由于您的 中存在绘图命令造成的\pgfextra。这里有一个测试文件来展示这种行为。

\documentclass[tikz]{standalone}

\pdfcompresslevel=0

\tikzset{ff/.style={append after command={\pgfextra\node {};\endpgfextra}}}

\begin{document}
\begin{tikzpicture}
\node[ff] (0,0) {XY};
\end{tikzpicture}
\end{document}

pgfcompresslevel=0意味着生成的 pdf 文件具有更易读的格式。从上面的代码中,您会在输出中看到两次以下 pdf 代码

BT
/F8 9.9626 Tf 3.321 3.321 Td [(XY)]TJ
ET

第一个位于 26-28 行,第二个位于 51-53 行。从材料\node {};中删除后pdfextra,会生成一个仅出现一次打印命令的 pdf 文件。

请注意,我没有为此使用任何背景、适合或矩阵库。

答案3

\documentclass[tikz]{standalone}
\usetikzlibrary{matrix,fit,backgrounds}
\tikzset{
  fill first cell/.style={
    append after command={
      \pgfextra
        \pgfonlayer{background}
          \tikzset{every node/.style=}
          \node[fit=(\tikzlastnode-\the\pgfmatrixcurrentcolumn-\the\pgfmatrixcurrentrow), inner sep=+0pt, fill=#1] {};
        \endpgfonlayer
      \endpgfextra
    }
  },
  fill first cell/.default=red!7
}
\begin{document}
\showoutput
\begin{tikzpicture}
\matrix (m) [matrix of nodes, fill first cell] {
  1 & 2 \\
  3 & 4 \\
};
\end{tikzpicture}
\end{document}

然后看看日志

$ grep "cmr/m/n/10" tkmatrix.log
.........................\OT1/cmr/m/n/10 1
.........................\OT1/cmr/m/n/10 2
.........................\OT1/cmr/m/n/10 3
.........................\OT1/cmr/m/n/10 4
.........................\OT1/cmr/m/n/10 1
.........................\OT1/cmr/m/n/10 2
.........................\OT1/cmr/m/n/10 3
.........................\OT1/cmr/m/n/10 4

您的观察是正确的,矩阵被绘制了两次。

相关内容