我定义了一个新环境,使用 fbox 在小页面周围绘制一种答案框。该环境还在答案框上方放置了一些文本。
这是一个最小的工作示例:
\documentclass{article}
\usepackage{listings}
\newsavebox{\mybox}
\newenvironment{ansbox}[1]{Write answer in the box:\newline
\begin{lrbox}{\mybox}\begin{minipage}[t][#1]{\linewidth}}
{\vfill\hfill\end{minipage}\end{lrbox}\fbox{\usebox{\mybox}}}
\setlength{\parskip}{\baselineskip}
\setlength{\parindent}{0ex}
\begin{document}
Description of problem.
\begin{ansbox}{2in}
%empty box
\end{ansbox}
What is your name?
\begin{ansbox}{2in}
My name is
\end{ansbox}
Implement a factorial function.
\begin{ansbox}{2in}
\begin{lstlisting}
def factorial(n):
\end{lstlisting}
\end{ansbox}
\end{document}
为了方便起见,我附上了第一页的截图:
如您所见,当框为空时,或者当它立即以列表环境开始时,会有一个垂直空间。我尝试四处搜索,但不知道这个空间是如何添加的,也不知道如何摆脱它。
另外,当它跳转到下一页时,怎样才能使“标题”文本与框保持在一起?
答案1
问题在于如何确保框的宽度;在这种情况下,最好添加与框一样宽的零高度规则。您还需要修剪一些宽度(对于\fboxsep
和\fboxrule
)。
\documentclass{article}
\usepackage{listings}
\newsavebox{\mybox}
\newenvironment{ansbox}[1]
{%
Write answer in the box:\\*
\begin{lrbox}{\mybox}
\begin{minipage}[t][#1]{\dimexpr\linewidth-2\fboxsep-2\fboxrule}
\hrule width \textwidth height 0pt
}
{\end{minipage}\end{lrbox}\fbox{\usebox{\mybox}}}
\setlength{\parskip}{\baselineskip}
\setlength{\parindent}{0ex}
\begin{document}
Description of problem.
\begin{ansbox}{1.5in}
%empty box
\end{ansbox}
What is your name?
\begin{ansbox}{1.5in}
My name is
\end{ansbox}
Implement a factorial function.
\begin{ansbox}{1.5in}
\begin{lstlisting}
def factorial(n):
\end{lstlisting}
\end{ansbox}
\end{document}
您的代码,带有\begin{ansbox}{1.5in}
,变成了
\begin{minipage}[t][1.5in]{\linewidth}
<environment's contents>
\vfill\hfill
\end{minipage}
当环境主体为空时,这使得
\vfill
\hfill
\par\vfil
(最后添加的标记是因为您想要一个[t]
minipage; 被\vfil
取消\vfill
)。框的参考点由 确定\vfill
。另一方面,对于非空内容,您有
My name is
\vfill
\hfill
\vfil
参考点位于顶部段落的基线;现在框的高度将测量为 M 的高度加上\fboxsep
;\fboxrule
这等于 6.83331+3+0.4=10.23331 点。这显然超出了阈值,因此 TeX 将\lineskip
在“在框中写答案:”行和框之间使用。在前一种情况下,框高度仅为 3.4pt,您看到的间隔是(因为上面的线没有深度)\baselineskip
减去 3.4pt。
根据我的解决方案,该框的高度始终为 3.4pt,因为零高度规则决定了参考点。
答案2
小型页面通常遵循框间距规则(\lineskip
而不是\baselineskip
),所以我喜欢\strut
在边框处添加 s。
除了上述问题之外,还有其他问题。坦白说,我很惊讶代码居然能运行。
首先,您不应该在环境定义中使用 \begin 和 \end,因为它们会无序展开。最好使用 environ 包来完成这类事情。
其次,lstlisting 不喜欢被放在任何东西里面(\hbox 除外)。该包有自己的环境软件。
如果您想避免文本和框之间出现分页符,可以使用 needspace 包。
\documentclass{article}
\usepackage{listings}
\usepackage{environ}
\newsavebox{\mybox}
\NewEnviron{ansbox}[1]{Write answer in the box:\strut\newline
\fbox{\begin{minipage}[t][#1][s]{\dimexpr \linewidth-2\fboxsep-2\fboxrule}
\strut\BODY\vfill\hfill
\end{minipage}}}
\lstnewenvironment{lstbox}{\global\setbox\mybox=\hbox\bgroup}{\egroup}
\setlength{\parskip}{\baselineskip}
\setlength{\parindent}{0ex}
\begin{document}
Description of problem.
\begin{ansbox}{2in}
\end{ansbox}
What is your name?
\begin{ansbox}{2in}
My name is
\end{ansbox}
Implement a factorial function.
\begin{lstbox}
def factorial(n):
\end{lstbox}
\begin{ansbox}{1in}
\usebox{\mybox}
\end{ansbox}
\end{document}