多列没有正确换行到第二列?

多列没有正确换行到第二列?

这个问题引出了包中的一个新功能:
multicol

我的包有问题multicol,我创建了一个示例演示来展示它。

当我minipage在其中放置 3 个特定高度的multicol框时,它会将其中 2 个框放在第一列,但第二个框太大而无法容纳该列(溢出页面),应该移至第二列。LateX 甚至会输出消息Overfull \vbox (145.52644pt too high) has occurred while \output is active

但是如果我将第二个框的高度改为40em,它会很好用,而且如果我使用不平衡的列(multicols*),那么它也能很好地工作,但我需要平衡列,并且我需要它自动处理列。

示例代码预览

\documentclass[12pt]{article}
\usepackage[paperwidth=8.5in, paperheight=11.0in, right=.25in,left=.25in,top=.75in,bottom=0.75in]{geometry}
\usepackage{multicol}

\newcommand{\drawbox}[1]
{
    % Draws a simple box given the height
    \noindent\fbox{%
        \begin{minipage}{0.9\linewidth}%
            \hfill \vspace{#1}%
        \end{minipage}
    } \\
}

\begin{document}
    \begin{multicols}{2}
        \drawbox{40em}

        % This box is too big to fit in the fist column, but would work great in the second colum
        \drawbox{30em} 
        \drawbox{40em}
    \end{multicols}
\end{document}

答案1

这是非常不合适的输入 ;-) 和多列的缺陷的混合。Multicol 最初是为文本平衡而设计的,算法基于此做出了一些假设。其中一个假设是,要从中截取列的样张材料具有适当数量的断点,可以实现这一点,特别是可以实现平衡。现在您的示例有两个属性:

  • 断点很少
  • 尽管如此,材料还是可以放在一页纸上(如果可以拆分的话)。当\drawbox用两个方框替换第二个方框时,可以看到后者15em。然后突然一切都平衡了,仍然适合放在页面上。

算法

现在平衡算法的工作原理大致如下:

  • 它测量整个厨房的平衡度,并根据该值推断出切割柱子的起始值。该起始点可能会受到影响,但在这里这无济于事。
  • 然后它切断柱子,最后一列接收所有剩余的材料。然后它检查最后一列的高度是否高于第一列的高度,如果是,则拒绝该解决方案。
  • 如果任何列的不良程度非常高(可定制),它也会拒绝当前试验。
  • 如果有未遵守的列分隔符,它也会拒绝试验。
  • 如果试验成功,则将使用找到的值,而不是将其增加一个点并重复算法。

如果最终值大于可用空间,则 multicol 会尝试通过将所有列压缩到可用空间中进行恢复。对于普通文本列,此方法可能会成功,因为页面上通常存在一些可收缩性,并且如果样张中有足够的断点,则超出量也不太可能很高。

应用于本示例

在这个例子中,这种方法当然会失败,因为算法会循环直到列高足够容纳第一列中的两个框(较小的切割值总是会使第二列太大)。当这种情况发生时,列大小与可用空间相差甚远,以至于任何压缩(即使有任何可以压缩的东西)都无济于事。

解决此问题的手动解决方案是在源中输入明确的分页符,即

\drawbox{30em} \pagebreak

这样 multicol 就会停止收集数据,然后生成一个正常页面。但这肯定是劳动密集型的,而且每当文档发生变化时就需要进行更改。

另一种方法是使用multicols*,但是这又有一个很大的缺点,那就是你根本无法平衡,因此第三页之后的任何文本\drawbox都会出现在下一页上,而不是(因为它可以)继续在同一页上。

多糖缺乏症(?)

现在有人可能会说,如果 multicol 进行平衡并找到类似上述示例的解决方案,它也应该拒绝该解决方案。但它接下来应该做什么呢?

一种可能性是得出结论,平衡毕竟不是正确的方法,而是先裁切另一张“正常”页面,然后在剩余的材料上进行平衡。对于这个特定示例,这种方法同样非常有效。但是,如果您查看以下示例,结果至少会值得怀疑:

\documentclass{article}

\usepackage[balancingshow]{multicol}

\setlength\textheight{5\baselineskip}

\begin{document}
\begin{multicols}{2}
1\\2\\3\\4\\5\\6

1\\2\\3\\4\\5\\6
\end{multicols}
\end{document}

使用当前算法,这将导致一页(略微过满)每列有六行,而使用拒绝这种平衡的算法,将导致第二页有两页每列只有一行。

所以现在我不确定这里最好的方法是什么。也许这需要另一个参数,例如\balancingoverflow保存平衡中的列允许“过满”的数量。

无论如何,我昨晚确实写了一个原型,可以做到这一点,如果有人想玩一下,请给我的“latex-project.org”地址发送电子邮件。

更新

我决定使用\maxbalancingoverflow默认为 12pt 的参数来实现这个新功能。新版本还修正了从右到左排版的算法。可以从 LaTeX2e SVN 源中获得:多列文件对于那些想立即试用它的人来说。随着 LaTeX2e 的下一个版本发布,它将出现在 CTAN 上。

截至 2014 年 5 月,CTAN 发布了包含此功能的新 LaTeX 版本。

答案2

显而易见的解决方案不是尝试平衡列,即使用multicols*而不是multicols。这可能不是您想要的。

多列包尽力解决 LaTeX 中多列排版的大多数问题,但它仍然无济于事,因为 LaTeX 不是为这些问题而设计的。如果您想要更好的解决方案,您应该切换到 ConTeXt。

当然,你可以将此作为 LaTeX 项目的错误进行归档,但我怀疑 Frank 不会高兴。

答案3

如果您想在双列工作流程中拥有多个小页面,我可以为不平衡的列提出一个案例吗?

虽然multicols*最后一页的列不平衡,但其他页面上仍然可能出现困难。

使用\raggedcolumnswithmulticols会导致每页的列不平衡。

在我看来,第二种选择可以让单个项目看起来不错,无需手动或详细干预(例如,通过调整 TeX 设置或移动项目来尝试改善适配,以防止单个文本块过度垂直拉伸。)我使用这样的结构来制作每周 2 列文档,其中包含多个简短或中等大小的项目,可能包括标题、副标题、多个段落和插图。我不希望任何单个文章分散在一列或一页上。我确实尝试过平衡列,但发现这很耗时,而且看起来有些混乱。

如果材料块无序且至少有些较短,那么您可以移动内容以允许排版引擎进行调整以生成平衡的列,但结果即使如此也可能令人失望。允许整个列不规则可以对项目进行排序(例如日记项目的日期顺序或重要性顺序或确定哪些文章获得“最佳”位置),并且只有严重不平衡才需要手动干预(例如三篇连续的文章每篇都超过半列,而至少两列连续的列大部分为空白)。它还可以加快工作流程,使我能够专注于内容和 TeX 以生成有吸引力的排版输出。

相关内容