这是一个后续问题在样式中添加节点
如果我使用以下代码,我会得到一个奇怪的行为:
代码
\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
您的观察是正确的,矩阵被绘制了两次。