Beamer 文章模式中的帧编号

Beamer 文章模式中的帧编号

我正在使用 beamer 包创建演示文稿。此外,我还想制作一份包含更多信息的讲义(因为演示文稿幻灯片不应包含太多文本)。为此,我使用文章模式。

为了让我的听众在讲义上做笔记,在讲义上标注帧编号会很有帮助。我使用以下代码实现了这一点:

\mode<article>{
    \renewcommand{\frametitle}[1]{\subsubsection*{#1 [Slide \insertframenumber]}}
}

除非您使用以下方式插入节起始帧,否则此方法非常有效

\AtBeginSection[] % nothing for \section*{}
{
    \begin{frame}
        \begin{center}
            \structure{\Huge \insertsection}
        \end{center}
    \end{frame}
}

问题是,\AtBeginSection在文章模式下,该功能不起作用。附加帧未插入,因此帧编号错误。

因此我做了以下操作来解决这个问题:

\mode<article>{ % repair frame numbers in article mode as there are no section start frames
    \newcommand*\oldsectionmacro{}%
    \let\oldsectionmacro\section%
    \renewcommand*\section{%
    \addtocounter{framenumber}{1}\oldsectionmacro}%
}

除非有,否则此方法有效\section*。在这种情况下,帧号会增加,但不应该增加,因为没有节起始帧。我可以避免使用,\section*但也有一些隐含的(目录、参考书目等)。

目前我手动更正了这个问题(见下文),目前它能正常工作,但我不喜欢它。有没有更好的方法?我可以重写\section*或使用\AtBeginSection文章模式或以不同的方式插入帧编号吗?

这是一个可以尝试的小例子:

\documentclass[a4paper]{scrartcl} % problem doesn't change if I use article instead
\usepackage{beamerarticle}
%\documentclass{beamer}

\usepackage[utf8]{inputenc}

\setbeamertemplate{footline}[frame number]

\mode<article>{
    % frame number in frametitle
    \renewcommand{\frametitle}[1]{\subsubsection*{#1 [Slide \insertframenumber]}}
}

% section start frame
% this has no effect in article mode
\AtBeginSection[] % nothing for \section*{}
{
    \begin{frame}
        \begin{center}
            \structure{\Huge \insertsection}
        \end{center}
    \end{frame}
}
\mode<article>{ % repair frame numbers in article mode as there are no section start frames
    \newcommand*\oldsectionmacro{}%
    \let\oldsectionmacro\section%
    \renewcommand*\section{%
    \addtocounter{framenumber}{1}\oldsectionmacro}%
%
%   \newcommand*\oldtocmacro{}%
%   \let\oldtocmacro\tableofcontents%
%   \renewcommand*\tableofcontents{%
%   \addtocounter{framenumber}{-1}\oldtocmacro}
}

\begin{document}

    \begin{frame}
        \tableofcontents
    \end{frame}

    \section{Section 1}

        \begin{frame}
            \frametitle{Frame A}

            Frame A
        \end{frame}

    \section{Section 2}
    %\section*{Section Star}

        \begin{frame}
            \frametitle{Frame B}

            Frame B
        \end{frame}

\end{document}

答案1

我认为,这里最简洁的方法是使它\AtBeginSection在 中工作beamerarticle。之所以不行,是因为\AtBeginSection宏通过定义在这些部分开头执行的钩子来工作。然而,在文章模式下,\section使用文档类定义的宏,因此这些钩子永远不会执行。

为了克服这个问题,需要重新定义\section宏。这有点复杂,因为它\@startsection 在内部调用,所以简单地将钩子添加到宏的末尾是行不通的。相反,需要一个围绕原始命令的完整“包装器”:

\mode<article>
\usepackage{xparse}
\makeatletter
\expandafter\let\expandafter\originalsection\expandafter=\csname @orig\string\section\endcsname
\RenewDocumentCommand{\section}{ D<>{} s o m }
{
  \alt<#1>
  {
    \IfBooleanTF {#2}
    {
      \originalsection*{#4}
      %\beamer@atbeginsections % breaks because section* is also used e.g. in the TOC
    }
    {
      \IfNoValueTF {#3} { \originalsection{#4} } { \originalsection[#3]{#4} }
      \beamer@atbeginsection
    }
  }
  {
    \beamer@secgobble
  }
}
\makeatother
\mode<all>

将此代码插入到文档的前言中,加载后beamerarticle。它所做的是将存储在宏中的宏beamer的原始、无含义的宏保存为具有“奇怪”名称的宏。之后,重新定义为执行原始的分段命令和随后的钩子。由于有带星号和不带星号的版本、可选参数和(可选)覆盖规范,我使用了\section@orig\section\originalsection\section\beamer@atbeginsection\sectionxparse这使得您可以以非常方便的方式定义此类宏。

现在您可以\AtBeginSection像往常一样使用 来插入章节开始帧。由于您可能不希望它们在文章模式中实际显示,\begin{frame}<article:0>因此您应该使用 (帧号仍然递增)。此外,您需要这样做,\def\insertsection{}因为此命令是未知的beamerarticle,否则会导致错误。

请注意,使用可选参数来\AtBeginSection定义带星号部分的钩子不起作用(上面的代码中注释掉了执行该操作的行)。原因是该操作\section*也用于目录等,在这些地方插入该操作会导致错误消息。

使用上述代码输出 MWE

在演示模式下(单击图像可查看完整尺寸):

演示模式下有五帧

在文章模式下:

beamerarticle 具有正确的帧编号

为了完整起见,可以找到产生上述结果的完整来源在 pastebin.com 上

编辑:xparse我以前重新定义的包\section依赖于实验性的 LaTeX3 内核。如果没有,你可以使用这个简单的 LaTeX2e 解决方案:

\mode<article>
\makeatletter
\expandafter\let\expandafter\originalsection\expandafter=\csname @orig\string\section\endcsname
\def\sectionwithhook{\@ifstar\@sectionwithhook\@@sectionwithhook}
\newcommand{\@sectionwithhook}[1]{\originalsection*{#1}}
\newcommand{\@@sectionwithhook}[2][]{\beamer@ifempty{#1}{\originalsection{#2}}{\originalsection[#1]{#2}}\beamer@atbeginsection}
\renewcommand<>{\section}{\alt#1{\sectionwithhook}{\beamer@secgobble}}
\makeatother
\mode<all>

\RenewDocumentCommand这将替换上面给出的整个代码,实现与一些辅助宏相同的功能。

相关内容