表格中的垂直对齐:m 列,行大小 - 最后一列存在问题

表格中的垂直对齐:m 列,行大小 - 最后一列存在问题

不幸的是,我有一个问题m-柱array包)在表格中调整行高.不知何故在最后一栏(仅在那里)文本是不居中垂直。

一探究竟:

在此处输入图片描述

\documentclass{article}
\usepackage{array}

\begin{document}

\begin{tabular}{|m{0.18cm}|m{0.18cm}|m{0.18cm}|}
\hline
a & b & c  \\[2ex]
\hline
0 & 0 & 0  \\
\hline
\end{tabular}

\end{document}

答案1

我认为这是一个错误,应该报告。对于没有耐心的人,可以进行调整:添加一个宽度为零且无填充的额外列。记得在有问题的行前面\\加上&

\documentclass{article}
\usepackage{array}

\begin{document}

\begin{tabular}{|m{0.18cm}|m{0.18cm}|m{0.18cm}|@{}m{0pt}@{}}
\hline
a & b & c &\\[2ex]
\hline
0 & 0 & 0 \\
\hline
\end{tabular}

\end{document}

答案2

@tohecz 的问题和回答都表明,对于前导标记“m”、“b”等的作用以及它与其\\可选参数的关系,至少存在一个根本的误解。

“m” 标记不是将其材料垂直置于可用空间的中心!

标记“c”、“l”和“r”产生水平单元格(一行高),它们的垂直对齐点只是每个单元格的基线。现在“p”、“m”和“b”生成一定宽度的单元格,可能还有几行。它们的垂直对齐分别是第一行、框的中间和底线。因此,如果我们稍微修改一下示例并运行:

\begin{tabular}{|p{0.18cm}|m{0.18cm}|b{0.18cm}|l|}
\hline
a\newline a & b\newline b & c\newline c\newline c& d \\
\hline
\end{tabular}

我们得到的是

在此处输入图片描述

因此,这一切都是相对于包含“d”的单元格的基线定位的。

现在可选参数\\仅将空间从对齐点向下扩展,即不是扩展实际单元格的大小。此外,它实际上并没有添加这个空间,而只是确保下一行至少有那么多空间。因此,例如,在上面的例子中,\\[2ex]不会产生任何效果,因为第一列中的单元格比这更靠下。

所以回到最初的问题及其输入:因为每个单元格只有一行,所以它们应该全部排成一行,但“m”会不是具有将内容置于可用空间中央的效果。相反,所请求的额外空间\\[2ex]会位于其后(或者应该位于其后... 这就是错误所在)。

因此让我们添加一个“l”列来避免这个错误,看看会发生什么:

\begin{tabular}{|m{0.18cm}|m{0.18cm}|m{0.18cm}|l|}
\hline
a & b & c & d \\[2ex]
\hline
a\newline a & b & c & d \\[2ex]
\hline
\end{tabular}

结果是

在此处输入图片描述

第一行显示,如果“m”内部只有一条线,并且 2ex 位于基线和下一行之间,则“m”和“l”并排放置。

第二行有一个“m”,里面有 2 行,您再次看到 2ex 从行基线移动到下一行,并且“m”也没有垂直居中。

因此建议使用额外的(隐藏行)

\begin{tabular}{|m{0.18cm}|m{0.18cm}|m{0.18cm}|@{}m{0pt}@{}}
\hline
a & b & c &             x\\[4ex]   % x normally being a space
\hline
a\newline a & b & c &   x\\[4ex]
\hline
\end{tabular}

实际上是在利用当前的错误,即隐藏问题中的“空间”实际上被向上推,以便可见行现在看起来或多或少处于中心位置(我通过在上面放置一个“x”使其可见):

在此处输入图片描述

因此,一旦这个问题得到解决,上述技巧就不再有效。

那么这个 bug 是什么?

这个问题非常微妙。要使带有规则的表格正常工作,无法垂直向下跳过\\[2ex],而是在某一行中放置一个不可见的规则/框,其深度比正常深度延伸2ex。如果不这样做,那么任何垂直规则都会在您添加额外垂直空间的地方中断。

这样做的缺点是,如果某一行具有不寻常的深度,则任何此类额外空间都可能显得不足,因为它是相对于“正常”深度进行测量的。

此外,将array这个不可见的支柱放在最后一行材料末尾的“错误”在于,对于 m 列来说,这是错误的,因为它们是垂直居中的。因此,在这里你会看到“c”向上移动,因为支柱最终以某种形式$\vcenter{... c \strut}$而不是结束$\vcenter{... c}$\strut

造成这种情况的原因是\halign用于构建表格的 TeX 底层机制的奇怪行为:当我们到达\\[2ex]LaTeX 已经处理$\vcenter{... c但尚未看到形成列的剩余材料时,即}$

因此,\\[ex]计算并添加支撑架,然后告诉 TeX 列已完成(\cr内部使用),这导致 TeX 将列模板的剩余部分(}$...加上空间和规则)复制到输入流中,然后你最终得到了里面的支撑架vcenter

一种可能的解决方法是延迟支柱的放置,以确保这种情况只发生在柱模板的正确部分。这反过来又有点棘手,因为到那时范围将改变值等等。所以这需要是一个全局操作。

\documentclass{article}
\usepackage{array}

\makeatletter
\def\@classz{\@classx
   \@tempcnta \count@
   \prepnext@tok
   \@addtopreamble{\ifcase \@chnum
      \hfil
      \d@llarbegin
      \insert@column
      \d@llarend\fmi@fix \hfil \or
      \hskip1sp\d@llarbegin \insert@column \d@llarend\fmi@fix \hfil \or
      \hfil\hskip1sp\d@llarbegin \insert@column \d@llarend\fmi@fix \or
   $\vcenter
   \@startpbox{\@nextchar}\insert@column \@endpbox $\fmi@fix
    \or
   \vtop \@startpbox{\@nextchar}\insert@column \@endpbox\fmi@fix \or
   \vbox \@startpbox{\@nextchar}\insert@column \@endpbox\fmi@fix
  \fi}\prepnext@tok}

\def\@mkpream#1{\gdef\@preamble{}\@lastchclass 4 \@firstamptrue
   \let\@sharp\relax \let\@startpbox\relax \let\@endpbox\relax
   \let\fmi@fix\relax
   \@temptokena{#1}\@tempswatrue
   \@whilesw\if@tempswa\fi{\@tempswafalse\the\NC@list}%
   \count@\m@ne
   \let\the@toks\relax
   \prepnext@tok
   \expandafter \@tfor \expandafter \@nextchar
    \expandafter :\expandafter =\the\@temptokena \do
   {\@testpach
   \ifcase \@chclass \@classz \or \@classi \or \@classii
     \or \save@decl \or \or \@classv \or \@classvi
     \or \@classvii \or \@classviii
     \or \@classx
     \or \@classx \fi
   \@lastchclass\@chclass}%
   \ifcase\@lastchclass
   \@acol \or
   \or
   \@acol \or
   \@preamerr \thr@@ \or
   \@preamerr \tw@ \@addtopreamble\@sharp \or
   \or
   \else  \@preamerr \@ne \fi
   \def\the@toks{\the\toks}}   


\def\@xargarraycr#1{\gdef\fmi@fix
 {\@tempdima #1\advance\@tempdima \dp\@arstrutbox
  \vrule \@depth\@tempdima \@width\z@\global\let\fmi@fix\relax}\cr}
\let\fmi@fix\relax

\makeatother

\begin{document}

\begin{tabular}{|m{0.18cm}|m{0.18cm}|}
\hline
a&c \\[2ex]
\hline
0& 0  \\
\hline
\end{tabular}

\end{document}

正如我所说的,这相当微妙,所以我不确定在不破坏很多其他东西的情况下进行这种类型的更改是否安全(毕竟array是一个非常古老的软件包(25年以上),它被使用得相当频繁,而且这个问题从一开始就存在。

无论如何,通过上述改变我们现在得到:

在此处输入图片描述

这正是我们应该做的,但也许不是人们在认为他们指定“m”列时所希望的。

更新

自 2018-04 版 LaTeX(甚至更早的一个版本)发布以来,实际错误已按上述概述进行了更正。这意味着(不幸的是)上面建议并标记为正确答案的技巧不再有效,但正如我所解释的那样,它基于对“m”规范的错误假设。

相关内容