15

I want to use \pause inside \only as in the example below. Sometimes it works well (see slides 2 and 3), but sometimes it doesn't (see slides 5 and 6). Why?

\documentclass{beamer}
\setbeamertemplate{footline}
{
  \hfill \insertframenumber{} / \inserttotalframenumber\hspace*{2ex}
}

\begin{document}
\begin{frame}
\frametitle{An example}
\only<1>{
insert a picture for instance
}
\pause
\only<2-3>{
\begin{itemize}
\item here is my first remark
\pause
\item and here is my second
\end{itemize}
}
\only<4>{
insert a 2nd picture
}
\pause
\only<5-6>{
\begin{itemize}
\item bla bla bla
\pause
\item ...
\end{itemize}
}
\end{frame}
\end{document}

On purpose, I want the footline to display the number of frames, that is only "1/1" in this example.

3
  • I believe omitting the \pause before \only<5-6> should help. (Ok, I just found it doesn't work. I'm afraid that as the manual says \pause cannot be mixed with <n-> syntax.)
    – yo'
    Jun 25, 2012 at 22:45
  • @tohecz thanks, but then why does it work on slides 2 and 3? Otherwise, would you know another way of doing it?
    – tflutre
    Jun 26, 2012 at 13:26
  • See my answer. If it does not work, let me know, I might look into it more tomorrow.
    – yo'
    Jun 28, 2012 at 20:41

3 Answers 3

14

I don't have my LaTeX here, but this ought to work. You have to rewrite each \pause to proper <n-m> syntax.

\begin{frame}
\frametitle{An example}
\only<1>{
insert a picture for instance
}
\only<2-3>{
\begin{itemize}
\item<2-3> here is my first remark
\item<3-3> and here is my second
\end{itemize}
}
\only<4>{
insert a 2nd picture
}
\only<5-6>{
\begin{itemize}
\item<5-6> bla bla bla
\item<6-6> ...
\end{itemize}
}
\end{frame}
23

This is due to the way that \pause works. As beamer processes a frame, it has an internal counter beamerpauses which it uses to work out what the current "logical" slide is. This is for use when you want to specify an overlaid command without referring to a specific slide, which is useful if you don't know (or haven't yet decided) what the specific slide number is. It is used when you have things like \item<+-> or \alert<.(1)>. It is incremented according to strict rules: basically, you need a + in the overlay. It is not incremented by things like \alert<3-4>. This is useful as it allows you to have a "main flow" (using +) and some things outside it, using explicit specifications.

Now the punchline. \pause is the same as \onslide<+->. So it uses the beamerpauses counter and increments it. But all those \onlys don't. Moreover, when the overlay specification for \only is not matched, it throws away its contents without processing it. So those \pauses inside \onlys are not processed when the overlay is not matched.

Let's consider what happens on slide 5.

\begin{frame}
\frametitle{An example}
\only<1>{% not present on slide 5
insert a picture for instance
}
\pause % on slide 5
\only<2-3>{% not on slide 5
\begin{itemize}
\item here is my first remark
\pause % not on slide 5
\item and here is my second
\end{itemize}
}
\only<4>{ % not on slide 5
insert a 2nd picture
}
\pause % on slide 5
\only<5-6>{ % on slide 5
\begin{itemize}
\item bla bla bla
\pause % on slide 5
\item ...
\end{itemize}
}
\end{frame}

Thus we are left with the following, and I'll count beamerpauses:

\begin{frame}
\frametitle{An example} % beamerpauses = 1
\pause % beamerpauses = 2
\pause % beamerpauses = 3
\begin{itemize}
\item bla bla bla
\pause % beamerpauses = 4
\item ...
\end{itemize}
\end{frame}

But we're on slide 5, so all of those pauses are considered as "dealt with" meaning that on slide 5, the entire contents are typeset.

There are various ways to fix this, but the simplest is to avoid mixing these two methods of specifying what goes on slides. Use \pause for the main flow and only use specific specifications for things outside the main flow. If all else fails, you can always manually set beamerpauses with a \setcounter{beamerpauses}{5}, for example.

1
  • thanks a lot for your detailed answer, I understand much better now the internals of all these commands
    – tflutre
    Jun 29, 2012 at 19:49
1

I often find that \pause doesn't behave like I expect it to do. To me, \pause should, in all cases, show the text following it one slide after the current text. I've implemented that as follows:

\makeatletter

\newcount\np@pauses
\np@pauses=\z@
\def\np@reset{%
  \loop\ifnum\np@pauses>\z@
    \csgundef{np@pause@\the\np@pauses}
    \global\advance\np@pauses by -1 %
  \repeat}

% At each frame, reset the \np@pause@ variables
\apptocmd{\beamer@reseteecodes}{\np@reset}{}{}

\newcommand{\np@pause}[1]{%
  \ifcsname np@pause@#1\endcsname%
    \beamer@@pause[\csname np@pause@#1\endcsname]%
  \else%
    \ifnum\beamer@coveringdepth=0 %
      \@tempcnta=\beamer@slideinframe%
      \advance\@tempcnta by 1 %
      \expandafter\xdef\csname np@pause@#1\endcsname{\the\@tempcnta}%
      \beamer@@pause[\the\@tempcnta]%
    \fi%
  \fi%
}
\newif\ifnp@patched
\let\np@beamer@frameslide\beamer@frameslide
\let\np@endbeamer@frameslide\endbeamer@frameslide
\RenewEnviron{beamer@frameslide}{%
  % Replace all \pause's by \np@pause{uniq-id}.
  \np@pauses=0%
  \loop%
    \global\advance\np@pauses by 1 %
    \edef\temp{\noexpand\np@pause{\the\np@pauses}}%
    \expandafter\patchcmd\expandafter{\expandafter\BODY\expandafter}%
      \expandafter{\expandafter\pause\expandafter}%
      \expandafter{\temp}%
      {\np@patchedtrue}{\np@patchedfalse}%
    \ifnp@patched%
  \repeat%
  \np@beamer@frameslide%
  \BODY%
  \np@endbeamer@frameslide%
}
\makeatother

This redefines the beamer@frameslide environment to change each \pause into \np@pause{uniq-id} where the uniq-id is simply the how many \pauses were read before. Then \np@pause waits until it is executed in a visible way (beamer@coveringdepth=0), stores the current slide number, and acts as a \pause[slide-nb + 1] from that point on.

This uses etoolbox and environ.

Your example together with that snippet has the "expected" behavior.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .