Beamer 笔记和 amsmath 环境

Beamer 笔记和 amsmath 环境

我正在考虑一个带有右侧注释的投影仪演示文稿。为了在注释和它们所指的内容之间建立更好的联系,我修改了命令\notes(使用zref's savepos),使注释文本打印在与文本出现的同一垂直位置。因此,将命令直接放在框架中并不总是可行的\notes,但有时它需要出现在不同的环境中。

这是为了激励,在大多数情况下效果很好。但是,请考虑这个 MWE:

\documentclass{beamer}

\usepackage{amsmath,pgfpages}

\setbeameroption{show notes on second screen=right}

\newcounter{notecounter}

\begin{document}
   \begin{frame}
      \begin{align*}
         a & = 1 \note{This is the first note: \arabic{notecounter}\stepcounter{notecounter}\\} \\
         b & = 2 \note{This is the second note \arabic{notecounter}\stepcounter{notecounter}\\}
      \end{align*}
   \end{frame}
\end{document}

这没有任何重新定义,只是使用我当然内部使用的普通 beamer 命令。注释页面将输出以下内容:

这是第一条注释:0

这是第二条注释 1

这是第一条注释:2

这是第二篇笔记 3

由于某种原因,注释在多行数学环境中出现时会重复出现(更糟糕的是,多次展开)(使用 和 进行测试aligngather带星号和不带星号)。但这似乎不是一个根本问题,您可能\note根本不会在数学模式下使用,因为它适用于\[ \]equation

有没有办法可以解决这个问题,当我改变对齐定义时它会完全弄乱我的间距\note

编辑:应 samcarter 的要求,我提供了一个包含部分代码的 MWE,用于提供对齐的注释。这非常简单,原始代码还包含错误放置的超链接的修复、合并比例框等,但这与显示问题无关。可能,tikzmark会使定位算法更优雅。由于我通常使用tikz,这对我来说不是一个缺点;但是,我认为实现只能从表面上解决问题:对齐可能是正确的(并且tikz会给出两次使用相同名称的警告),但两个相同的注释会打印在彼此的顶部。

\documentclass{beamer}

\usepackage{amsmath,pgfpages,zref-user,zref-savepos}

\setbeameroption{show notes on second screen=right}
\setbeamertemplate{note page}[plain]

\newcounter{notecounter}

\makeatletter
\let\oldnote\note
\newcounter{pposes}
\newcounter{poses}
\AtBeginNote{%
   \setcounter{poses}{0}%
}
\AtEndNote{%
   \setcounter{poses}{0}%
   \stepcounter{pposes}%
}
\renewcommand<>{\note}[1]{%
   \only#2{%
      \stepcounter{poses}%
      \vbox to 0pt{%
         \edef\l{p\the\value{pposes}-\the\value{poses}}%
         \zsaveposy{\l}%
         \zrefused{\l}%
         \oldnote{%
            \stepcounter{poses}%
            \edef\l{p\the\value{pposes}-\the\value{poses}}%
            \zref@ifrefundefined{\l}{}{%
               \parbox[l][0pt][t]{0pt}{%
                  \hfuzz=\maxdimen%
                  \parbox{\textwidth}{%
                     \vspace{\dimexpr\paperheight - \zposy{\l}sp - 6mm}%
                     #1%
                  }%
               }%
            }%
         }%
      }%
   }%
}

\begin{document}
   \begin{frame}
      \begin{align*}
         a & = 1 \note{This is the first note: \arabic{notecounter}\stepcounter{notecounter}} \\
         b & = 2 \note{This is the second note \arabic{notecounter}\stepcounter{notecounter}}
      \end{align*}
      Problem \note{This is the third note: \arabic{notecounter}\stepcounter{notecounter}}
   \end{frame}
\end{document}

请注意,这样一来,问题就发生了变化:现在不是音符可见两次(因为宏没有找到第二次出现的相关位置),而是在 -environment\note之后使用该命令align,首先给出未打印的重复音符。因此,此 MWE 生成正确对齐的前两个音符,然后再次生成第一个音符,该音符未与“问题”的位置对齐。重复的第二个音符和实际的第三个音符根本没有显示。

答案1

这个问题是由于align环境需要在实际打印任何内容之前执行一些测量和计算而引起的。为此,它首先必须排版框寄存器中的所有内容,这些内容不会打印,只会进行测量。之后所有内容都会再次排版,这一次是真实的。

此过程的结果是,在align环境内进行的任何分配都会执行两次,这就是您遇到的情况。 (注意:测量完成后,所有 LaTeX 计数器都会重置,因此在环境内\setcounter可以\stepcounter按预期工作align。)

规避此问题的一种方法是使用条件\ifmeasuring@,在执行这些测量时将其设置为 true。以下内容来自amsmath文档

\ifmeasuring@
所有显示环境都会排版​​两次 - 一次是在“测量”阶段,然后再次在“生产”阶段;\ifmeasuring@将用于确定我们处于哪种情况,以便我们采取适当的措施。

因此,您可以重新定义,\note以便它在测量阶段不执行任何操作,如下所示:

\documentclass{beamer}

\usepackage{amsmath,pgfpages}

\makeatletter
\let\originalnote\note
\renewcommand<>\note[2][]{\ifmeasuring@\else\originalnote#3[#1]{#2}\fi}
\makeatother

\setbeameroption{show notes on second screen=right}

\newcounter{notecounter}

\begin{document}
   \begin{frame}
      \begin{align*}
         a & = 1 \note{This is the first note: \arabic{notecounter}\stepcounter{notecounter}\\} \\
         b & = 2 \note{This is the second note \arabic{notecounter}\stepcounter{notecounter}\\}
      \end{align*}
   \end{frame}
\end{document}

在此处输入图片描述

答案2

由于某种原因,其中的代码align*被执行了两次。因此,前两个注释也被定义了两次。注释的标签分别为 p0-1、p0-2、p0-1、p0-2 和 p0-3(请注意重复的标签)。Beamer 现在已存储了 5 个注释。在排版注释页面时,您的代码会尝试使用标签 p0-1 到 p0-5 来表示存储的注释。当然,最后两个是未知的。

您的代码存储的位置是正确的。但现在,第三个存储的音符是第一个的副本。这是用第三个真实音符的位置设置的。其他音符没有给出,因为现在使用的标签是未定义的。

一种可能的解决方案是阻止第一次执行注释(我也尝试阻止第二次执行,但没有成功)。这里使用(ma 表示数学对齐)完成此操作,仅当标志为\manote时才执行。标志设置为(需要包)。不幸的是,无法使用重置,因为此时已经太晚了。因此,标志的设置方式有两种:a)使用(内部设置标志)作为最后一个注释或 b)在最后一个之后使用,但在环境中。\note\ifexecutenotetruefalse\AtBeginEnvironmentetoolbox\AtEndEnvironment\lmanote\executemanotes\manote

\AtBeginEnvironment{someenv}{\global\executemanotefalse}对于每个其他环境,您必须在序言中添加一行。

我保留了一些(注释掉的)调试代码,因为它对于弄清楚发生了什么非常有用。如果您的完整代码出现一些问题,它可能会有所帮助。代码将一些信息写入日志文件。

在此处输入图片描述

\documentclass{beamer}

\usepackage{amsmath,pgfpages,zref-user,zref-savepos}

\usepackage{etoolbox} % <---- new

\setbeameroption{show notes on second screen=right}
\setbeamertemplate{note page}[plain]

\newcounter{notecounter}

\makeatletter
\let\oldnote\note
\newcounter{pposes}
\newcounter{poses}
\AtBeginNote{%
   \setcounter{poses}{0}%
}
\AtEndNote{%
   \setcounter{poses}{0}%
   \stepcounter{pposes}%
}
\renewcommand<>{\note}[1]{%
   \only#2{%
      \stepcounter{poses}%
      \vbox to 0pt{%
         \edef\l{p\the\value{pposes}-\the\value{poses}}%
%         \typeout{XXXXXXXXXXXXXXXXXXXX label: \l}%
         \zsaveposy{\l}%
         \zrefused{\l}%
%         \typeout{AAAAAAAAAAAAAAAAAAAA pos: \the\dimexpr\paperheight - \zposy{\l}sp - 6mm}%
         \oldnote{%
            \stepcounter{poses}%
            \edef\l{p\the\value{pposes}-\the\value{poses}}%
%            \typeout{YYYYYYYYYYYYYYYYYYYY label: \l}%
            \zref@ifrefundefined{\l}{%
%               \typeout{ZZZZZZZZZZZZZZZZZZZZ label undefined: \l}%
            }{%
%               \typeout{ZZZZZZZZZZZZZZZZZZZZ label defined: \l}%
               \parbox[l][0pt][t]{0pt}{%
                  \hfuzz=\maxdimen%
                  \parbox{\textwidth}{%
                     \vspace{\dimexpr\paperheight - \zposy{\l}sp - 6mm}%
%                     \typeout{BBBBBBBBBBBBBBBBBBBB pos: \the\dimexpr\paperheight - \zposy{\l}sp - 6mm}%
                     #1%
                  }%
               }%
            }%
         }%
      }%
   }%
}

%-------------------------------------------------------------------------------
\newif\ifexecutemanote
\newcommand<>{\manote}[1]{%
    \ifexecutemanote
        \note#2{#1}%
    \fi
}
\newcommand<>{\lmanote}[1]{%
    \manote#2{#1}%
    \global\executemanotetrue
}
\newcommand*{\executemanotes}{\global\executemanotetrue}

\AtBeginEnvironment{align*}{\global\executemanotefalse}
%-------------------------------------------------------------------------------

\begin{document}
   \begin{frame}
      \begin{align*}
         a & = 1 \note{This is the first note: \arabic{notecounter}\stepcounter{notecounter}} \\
         b & = 2 \note{This is the second note \arabic{notecounter}\stepcounter{notecounter}}
      \end{align*}
      Problem \note{This is the third note: \arabic{notecounter}\stepcounter{notecounter}}
%      \typeout{EEEEEEEEEEEEEEEEEEEE: with note}
   \end{frame}
%   \typeout{EEEEEEEEEEEEEEEEEEEE: 1. frame end}

   \begin{frame}
      \begin{align*}
         a & = 1 \manote{This is the first note: \arabic{notecounter}\stepcounter{notecounter}} \\
         b & = 2 \lmanote{This is the second note \arabic{notecounter}\stepcounter{notecounter}}
      \end{align*}
      or
      \begin{align*}
         a & = 1 \manote{This is the third note: \arabic{notecounter}\stepcounter{notecounter}} \\
         b & = 2 \manote{This is the fourth note \arabic{notecounter}\stepcounter{notecounter}}
         \executemanotes
      \end{align*}
      Problem \note{This is the fifth note: \arabic{notecounter}\stepcounter{notecounter}}
%      \typeout{EEEEEEEEEEEEEEEEEEEE: with tablenote}
   \end{frame}
%   \typeout{EEEEEEEEEEEEEEEEEEEE: 2. frame end}

   \begin{frame}
      \begin{tabular}{cc}
         a & = 1 \note{This is the first note: \arabic{notecounter}\stepcounter{notecounter}} \\
         b & = 2 \note{This is the second note \arabic{notecounter}\stepcounter{notecounter}}
      \end{tabular}

      Problem \note{This is the third note: \arabic{notecounter}\stepcounter{notecounter}}
%      \typeout{EEEEEEEEEEEEEEEEEEEE: with tabular}
   \end{frame}
%   \typeout{EEEEEEEEEEEEEEEEEEEE: 3. frame end}
\end{document}

相关内容