如何使用 \beamer@frametitle 值作为 \settowidth 的参数

如何使用 \beamer@frametitle 值作为 \settowidth 的参数

我正在定制一个beamer主题,我的工作场所中许多人都必须使用它。每当框架标题超过两行时,我都希望显示错误。请不要问为什么标题这么长。所以我认为通过定义自定义长度并将其设置为框架标题的宽度,我可以将这个自定义长度与阈值进行比较并显示错误。但是我无法将自定义长度的宽度设置为框架标题。我收到的错误是未定义的控制序列。MWE 如下:

\documentclass{beamer}

\makeatletter
    \newlength \myl
    \def \cm {\beamer@frametitle}
    \settowidth{\myl}{\cm}  %error ! Undefined control sequence.
    %\settowidth{\myl}{Example frame} %68.2551pt
\makeatother

\begin{document}
    \begin{frame}{Example frame}
        \the \myl  
    \end{frame}
\end{document}

我对自定义主题还不熟悉。所以如果有人能帮我解决长度大于比较的 if 构造问题。我会非常感激。我已经尝试使用\if\ifxwikibooks 上的可用方法,但都没有用。

答案1

以下示例修补\frametitle命令以更新长度\titlelen,给出当前主题字体下标题的长度:

在此处输入图片描述

\documentclass{beamer}

\let\Tiny\tiny% http://tex.stackexchange.com/a/94159/5764

\usepackage{etoolbox}

\makeatletter
\newlength{\titlelen}
\tracingpatches
\patchcmd{\beamer@@frametitle}% <cmd>
  {\gdef\beamer@frametitle}% <search>
  {\settowidth{\titlelen}{\usebeamerfont{frametitle}#2}%
   % ...condition here, if necessary...
   \gdef\beamer@frametitle}% <replace>
  {}{}% <success><failure>
\makeatother

\begin{document}

\begin{frame}{Example frame}

  {\usebeamerfont{frametitle}Example frame}

  \rule{\titlelen}{1pt}

  \the\titlelen

\end{frame}

\end{document}

虽然可以按照上述步骤采取一些措施,但更改后的宏 - \beamer@@frametitle- 不仅通过\beamer@frametitle,而且通过 构建\insertframetitle框架标题设置。因此,如果您希望在用户输入(例如)“这是一个超长的框架标题,实际上太长”时将框架标题更改为(例如)“太长”,则以下设置可能会更好:

在此处输入图片描述

\documentclass{beamer}

\let\Tiny\tiny% http://tex.stackexchange.com/a/94159/5764

\makeatletter
\newlength{\titlelen}
\long\def\beamer@@frametitle[#1]#2{%
  \settowidth{\titlelen}{\usebeamerfont{frametitle}#2}%
  \beamer@ifempty{#2}{}{%
    \ifdim\the\titlelen>300pt\relax
      \gdef\beamer@frametitle{Too long}%
    \else
      \gdef\beamer@frametitle{#2}%
    \fi
    \gdef\insertframetitle{{\beamer@frametitle\ifnum\beamer@autobreakcount>0\relax{}\space\usebeamertemplate*{frametitle continuation}\fi}}%
    \gdef\beamer@shortframetitle{#1}%
  }%
}
\makeatother

\begin{document}

\begin{frame}{This is a super long frame title that is actually too long}

  {\usebeamerfont{frametitle}Example frame}

  \rule{\titlelen}{1pt}

  \the\titlelen

\end{frame}

\end{document}

答案2

首先,为什么不直接使用\insertframetitle?其次,我认为没有\beamer@frametitle在框架之外定义。这就是您可能收到错误消息的原因。第三,您还应该在计算中考虑字体(形状、大小等)。看看这个例子。

\documentclass{beamer}

\newlength\myframetitlelength

\begin{document}
    \begin{frame}{Example frame}
        \insertframetitle
        \settowidth{\myframetitlelength}{\insertframetitle}
        \the\myframetitlelength

        Example frame%
        \settowidth{\myframetitlelength}{Example frame}
        \the\myframetitlelength

        {\usebeamerfont{frametitle}\insertframetitle}
        \settowidth{\myframetitlelength}{\usebeamerfont{frametitle}\insertframetitle}
        \the\myframetitlelength
    \end{frame}
\end{document}

输出: beamer_frametitle


此示例说明了为什么使用\insertframetitle是有意义的。阈值 (100pt) 设置在第一和第二帧的两个宽度之间。显然,您应该将其更改为更高的值。

\documentclass{beamer}
\usepackage{lipsum}

\newlength\myframetitlelength

\addtobeamertemplate{frametitle}{%
  \settowidth{\myframetitlelength}{\usebeamerfont{frametitle}\insertframetitle}%
  \ifdim\myframetitlelength>100pt%
    \PackageWarning{}{Frametitle is too long: \the\myframetitlelength.}%
  \fi%
}

\begin{document}
    \begin{frame}[allowframebreaks]{Example frame}
        \lipsum[1-2]
    \end{frame}
\end{document}

相关内容