在某些情况下,Multicol 会导致文本叠加。如何避免这种情况?

在某些情况下,Multicol 会导致文本叠加。如何避免这种情况?

我遇到过一种情况,即multicols环境的最后一页会出现重叠文本。据我所知,当环境的\columnbreak倒数第二页和最后一页上都有强制 s时,就会出现问题multicols 倒数第二页的列数较短。如果我将倒数第二页的列数填满,则不会出现此问题。

MWE 说明了这种行为:

\documentclass{article}
\usepackage[debugshow]{multicol}
\usepackage{lipsum}

\raggedbottom
\raggedcolumns
\setlength\columnsep{0.5in}
\setlength\columnseprule{.5pt}

\begin{document}
\begin{multicols}{2}

\lipsum[4]
% Uncommenting either this rule or the one in the next column
% balances the columns on the last page
%\rule{1pt}{350pt}

\columnbreak

\lipsum[4]

%\rule{1pt}{350pt}

\columnbreak

\lipsum[1]

\columnbreak

\lipsum[4]

\end{multicols}

And some concluding text
\end{document}

最终页面上的结果列如下所示:

MWE 的最后一列

MWE 被精简了很多,以至于我这样做的动机可能不明确。我只想说,我正在设置需要这种布局的考试问题,并且考虑到这些问题设置方式的其他限制,短列和 s 是不可避免的\columnbreak。另请注意,我不能使用,multicols*因为我需要在环境下方和同一页面上的单列文本multicols。同样,我查看并拒绝了所有平行列包,因为它们有限制,使它们对我来说无法使用。

我尝试查看日志文件以了解 divinemulticol的推理,但我不明白为什么会发生这种情况。我尝试调整参数,例如,finalcolumnbadness也没有得到任何有用的结果。

我希望发生的行为是,当我在文本\columnbreak的最后一页上发出一个(并且有效)时,应该相信我知道自己在做什么,并简单地将列高设置为两列中较大的一个。我该如何实现这一点?multicols\raggedcolumnsmulticol

答案1

此解决方案使用colaction选项来确定是否使用\columnbreak\pagebreak自动。它通过在 AUX 文件中写入列号来工作,因此需要(至少)两次运行。

\documentclass{article}
\usepackage[debugshow,colaction]{multicol}
\usepackage{lipsum}

\raggedbottom
\raggedcolumns
\setlength\columnsep{0.5in}
\setlength\columnseprule{.5pt}

\let\oldcolumnbreak=\columnbreak
\renewcommand{\columnbreak}{\docolaction{\pagebreak}{\oldcolumnbreak}{\oldcolumnbreak}}

\begin{document}
\begin{multicols}{2}

\lipsum[4]
% Uncommenting either this rule or the one in the next column
% balances the columns on the last page
%\rule{1pt}{350pt}

\columnbreak

\lipsum[4]

%\rule{1pt}{350pt}

\columnbreak

\lipsum[1]

\columnbreak

\lipsum[4]

\end{multicols}

And some concluding text
\end{document}

答案2

这是一个有趣的场景。基本上,接下来会发生以下情况:多列主体太短,如果没有分栏符,所有内容都可以放在一页上。因此,它到达环境的末尾并开始平衡,即使里面实际上有 3 个分栏符。

结果平衡失败,恢复尝试是剪切一个正常页面,其余材料被推回以便稍后重新考虑。到目前为止一切顺利。

但是,在剪切第一页后,平衡输出例程在重新聚集后仍然有效(以平衡剩余材料)。通常情况下,这样做是可行的,但这次材料中仍然有一个列断裂惩罚,而列断裂惩罚是一种强制惩罚,因此 OR 材料的重新聚集在此点停止,并且仅平衡到此点的材料。

然后将其推回(作为整个页面宽度的单个框),就好像它是多列环境的末尾一样,但由于它实际上不是全部材料,因此代码现在收集其余部分并进行另一次平衡。

由于第一次平衡产生了一个全宽的盒子(现在最终位于第二次平衡的第一列),它会覆盖第二列的一部分,这就是人们所看到的。

这个问题很难解决,因为代码\columnbreak从未打算用作拆分所有列的通用标记,而只是在找不到正确断点时帮助多列处理,这就是为什么我从未考虑过最终出现比平衡中有效的列断点更多的情况。因此,我不得不对整体逻辑进行大量更改(希望是正确的)。

因此,请尝试以下操作,看看它是否适用于您的真实文档(我尝试过的示例和您的 MWE 都不适用)。

\usepackage[balancingshow]{multicol}

\usepackage{etoolbox}

\makeatletter
\patchcmd\endmulticols
  {\penalty\z@
   \output{\balance@columns@out}%
   \eject}
  {\penalty-\@Mvi}
  {\typeout{Success patching}}{\ERROR}


\patchcmd\speci@ls
  {\else \PackageWarningNoLine{multicol}}
  {\else
      \ifnum\outputpenalty = -\@Mvi
        \mult@info\@ne{End penalty of multicols seen}%
        \outputpenalty\@M 
        \balance@columns@out
    \else \PackageWarningNoLine{multicol}}
  {\typeout{Success patching}}{\ERROR}

\patchcmd\speci@ls
  {\else \@doclearpage \fi}
  {\fi \else \@doclearpage \fi}
  {\typeout{Success patching}}{\ERROR}

\patchcmd\balance@columns@out
  {\unvbox\mult@box}
  {\unvbox\mult@box \penalty-\@Mvi}
  {\typeout{Success patching}}{\ERROR}

\mathchardef\@Mvi=10006
\makeatother

相关内容