Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

What I would like to achieve is, in a later frame, I would want a specific figure to reappear so that I can talk more about it, preferably keeping the original figure counter number. In both occurrences, there would be some text or other stuff accompanying the figure.

This question is similar to this, this, or this. The solution in the first link seems to be too manual, the second seems nice but I couldn't get it to compile in a beamer document, and the third only touches the issue about figure counter. I tried to use a lrbox environment to save the contents of the figure, but this also does not seem to work:

\documentclass{beamer}
\usepackage{tikz}
\setbeamertemplate{caption}{{\small\bfseries\MakeUppercase{\insertcaptionname~\insertcaptionnumber}}\quad\insertcaption}
\newsavebox{\myfigurebox}

\begin{document}
\begin{frame}{First Frame}
  \begin{lrbox}{\myfigurebox}
    \begin{tikzpicture}
      \draw (0,0) -- ++(75:1 cm) -- ++(-75:1 cm);
    \end{tikzpicture}
  \end{lrbox}

  \begin{figure}
    \centering
    \usebox{\myfigurebox}
    \caption{Description.}
  \end{figure}
  Some text.
\end{frame}
\begin{frame}{Other Frame}
  \begin{figure}
    \centering
    \usebox{\myfigurebox}
    \caption{Description (again).}
  \end{figure}
  More text.
\end{frame}
\end{document}

Other variations are also tried, e.g. surrounding the figure environment with lrbox, moving lrbox outside a frame etc, but these didn't work either.

Right now, the only close solution I had is to use overlay specifications and an \againframe, but this messes up the equation numbers or other counters.

\documentclass{beamer}
\usepackage{tikz}
\setbeamertemplate{caption}{{\small\bfseries\MakeUppercase{\insertcaptionname~\insertcaptionnumber}}\quad\insertcaption}

\begin{document}
\begin{frame}<1>[label=myframe]
\frametitle<1>{First Frame}
\frametitle<2>{Other Frame}
  \begin{figure}
    \centering
    \begin{tikzpicture}
      \draw (0,0) -- ++(75:1 cm) -- ++(-75:1 cm);
    \end{tikzpicture}
    \caption{Description.}
  \end{figure}
\begin{overprint}
\onslide<1>
  Some text. 
\onslide<2>
  More text. % imagine there are some equations or other counters here; the equation numbering would be wrong
\end{overprint}
\end{frame}
% later...
\againframe<2>{myframe}
\end{document}

And this way of "hacking" might get out of control if the same figure is repeated a lot of different times...

share|improve this question
    
Independent from the problem at hand don't number your figures in a presentation specifically for this reason. It imposes an artificial structure that is not even required. Nobody's counting anyway. It's much better to say out loud, Let's go back to .... which cues the audience that it was shown before. –  percusse Nov 7 '12 at 14:41
    
I'd also avoid figure. Usually in a presentation one cares where a figure ends up so doesn't want it to float. –  Loop Space Nov 7 '12 at 14:43
    
@AndrewStacey: figure in beamer does not float, but rather is a 'fake float' to keep the same interface, defined in beamerbaselocalstructure.sty. –  cyberSingularity Nov 7 '12 at 14:53
    
@cyberSingularity Learn something new every day - didn't know that. –  Loop Space Nov 7 '12 at 15:33
    
@AndrewStacey: hehe, never thought I'd know something about LaTeX that you didn't! ;) –  cyberSingularity Nov 7 '12 at 15:49
show 4 more comments

1 Answer 1

up vote 4 down vote accepted
  • Having the \begin{lrbox} etc within a frame makes it local to the frame, hence it cannot be recalled later, unless defining a globallrbox environment and using that instead. Such a definition might be done by

    \usepackage{etoolbox}
    \usepackage{letltxmacro}
    \LetLtxMacro{\globallrbox}{\lrbox}
    \LetLtxMacro{\endgloballrbox}{\endlrbox}
    \patchcmd{\globallrbox}{\setbox}{\global\setbox}{}{\showtokens{patching globallrbox failed}}
    
  • The figure numbers will be different because the \caption command is responsible for assigning the numbers, and you have two \caption commands. Probably trying to put the whole figure environment within a box is not going to be easy (and you can't put the caption in the box without the figure environment either), and does not allow you to append the text "(again)" to the caption the second time, so better to fiddle with the labels/counters, as I have done below, extending the example to show the effect on having other figures in between.

In the following I have avoided using the globallrbox environment and moved the lrbox outside of the frame to better illustrate the various approaches. You could probably tidy this up further by providing additional macros/environments for saving and recalling figures.

\documentclass{beamer}

\usepackage{tikz}
\setbeamertemplate{caption}{{\small\bfseries\MakeUppercase{\insertcaptionname~\insertcaptionnumber}}\quad\insertcaption}
\newsavebox{\myfigurebox}

\makeatletter
\newcommand*{\localsetcounter}[2]{% same as LaTeX's \setcounter, but removed the \global
    \@ifundefined {c@#1}{\@nocounterr {#1}}%
    {\csname c@#1\endcsname #2\relax}%
}

\newcommand*{\reusefigurecounter}[1]{%only use this within your figure environment to keep the changes local to that environment, and before the \caption command!
    \localsetcounter{figure}{\getrefnumber{#1}}%
    \let\refstepcounter\@gobble
}
\makeatother

\setcounter{errorcontextlines}{\maxdimen}

\begin{document}

  \begin{lrbox}{\myfigurebox}% the lrbox is outside any frames, but after \begin{document} so that the right fonts and things are set up, and before we first want to use it
    \centering
    \begin{tikzpicture}
      \draw (0,0) -- ++(75:1 cm) -- ++(-75:1 cm);
    \end{tikzpicture}
  \end{lrbox}

\begin{frame}{First Frame}
  \begin{figure}
    \usebox{\myfigurebox}
    \caption{Description.}
    \label{myfigure}
  \end{figure}
  Some text.
\end{frame}

\begin{frame}{Another Frame}
  \begin{figure}
    something else
    \caption{Description.}
  \end{figure}
  Some text.
\end{frame}

\begin{frame}{Other Frame}
  \begin{figure}
    \centering
    \usebox{\myfigurebox}
    \reusefigurecounter{myfigure}
    \caption{Description (again).}
  \end{figure}
  More text.
\end{frame}


\begin{frame}{Another Frame}
  \begin{figure}
    something else entirely
    \caption{Description.}
  \end{figure}
  Some text.
\end{frame}
\end{document}

Update: slightly better interface?

With this version, use a savefigure environment anywhere before you want the first copy of that figure to appear, providing a label in the first argument by which to recall it later. The figure is then called up or recalled with either the \figurefirstuse or \reusefigure command, depending whether it has been shown already or not. The arguments to these commands are the label name and the caption, which need not be the same for all recalls of the same image. It does not currently save any previously used caption(s) automatically.

Not sure if all this stuff is necessary or elegant, but seems to work, now also when there are overlays. Note that there are some limitations with regards to error handling at the very least. It is not easy to automatically determine if the figure is being used for the first time or not because beamer resets the figure counter when it reprocesses the frame for multiple slides (ie overlays and pauses), hence I have given up on trying to do that for now.

There is also a figureandsave environment which saves the figure and shows it in the same place, internally calling the above commands. Takes the same arguments as for \figurefirstuse in this case.

I have left the previous version above as it may be clearer what's actually going on. The following example should hopefully illustrate the new interface better than my description of it.

\documentclass{beamer}

\usepackage{tikz}
\setbeamertemplate{caption}{{\small\bfseries\MakeUppercase{\insertcaptionname~\insertcaptionnumber}}\quad\insertcaption}

\makeatletter
\newcommand*{\localsetcounter}[2]{% same as LaTeX's \setcounter, but removed the \global
    \@ifundefined {c@#1}{\@nocounterr {#1}}%
    {\csname c@#1\endcsname #2\relax}%
}

\newcommand*{\reusefigurecounter}[1]{%#1=label, only use this within your figure environment to keep the changes local to that environment, and before the \caption command!
    \localsetcounter{figure}{\getrefnumber{#1}}%
    \let\refstepcounter\@gobble
}

\usepackage{etoolbox}
\usepackage{letltxmacro}
\LetLtxMacro{\globallrbox}{\lrbox}
\LetLtxMacro{\endgloballrbox}{\endlrbox}
\patchcmd{\globallrbox}{\setbox}{\global\setbox}{}{\showtokens{patching globallrbox failed}}

\newenvironment{figureandsave}[2]{% parameters #1=label name,#2=caption
    \def\currsavefigurecaption{#2}%
    \def\currsavefigurename{#1}%
    \begin{savefigure}{#1}}%
    {\end{savefigure}%
    \figurefirstuse{\currsavefigurename}{\currsavefigurecaption}%
    }

% can use savefigure within or outside of a frame, but always after \begin{document}
\newenvironment*{savefigure}[1]{% parameters #1=label name
    \expandafter\newbox\expandafter{\csname savedfigure#1box\endcsname}%use \newbox instead of \newsavebox as we have to allow beamer to process the same figure multiple times if a frame contains multiple slides
    \begin{globallrbox}{\csname savedfigure#1box\endcsname}%
    }
    {\end{globallrbox}}

% use \figurefirstuse the first time you want to show the figure
\newcommand\figurefirstuse[2]{% parameters #1=label name,#2=caption
    \@ifundefined{savedfigure#1box}{\errmessage{figure #1 hasn't been saved yet}}{%
    % calling this multiple times for the same figure will result in it having multiple numbers assigned to it and multiply defined label issues
    \begin{figure}%
        \usebox{\csname savedfigure#1box\endcsname}%
        \caption{#2}%
        \label{savedfigure#1}%
    \end{figure}}}

% use \reusefigure if the figure has already been shown, and you want to show it again
\newcommand\reusefigure[2]{% parameters #1=label name, #2=new caption
    \@ifundefined{savedfigure#1box}{\errmessage{figure #1 hasn't been saved yet}}{%
    % no easy way to test if the figure has been used or not yet, but will be numbered Figure 0 if not!
    \begin{figure}%
        \usebox{\csname savedfigure#1box\endcsname}%
        \reusefigurecounter{savedfigure#1}%
        \caption{#2}%
    \end{figure}}}
\makeatother


\begin{document}

\begin{savefigure}{test}
    World.
\end{savefigure}

\begin{frame}{First Frame}
    \begin{figureandsave}{myfigure}{Description.}
        \centering
        \begin{tikzpicture}
            \draw (0,0) -- ++(75:1 cm) -- ++(-75:1 cm);
        \end{tikzpicture}
    \end{figureandsave}
    \pause
    Some text after a pause.
\end{frame}

\begin{frame}{In between}
    \begin{figure}
        A different figure
        \caption{For testing}
    \end{figure}

    \pause
    \figurefirstuse{test}{Hello}
    \reusefigure{test}{Hello again}
\end{frame}

\begin{frame}{Other Frame}
    \reusefigure{myfigure}{Description (again).}

    \begin{figure}
        A second figure on the same frame.
        \caption{With a number}
    \end{figure}

    More text.
\end{frame}

\end{document}
share|improve this answer
    
A big thanks to you, cyberSingularity! This is exactly what I am looking for. Your code works perfectly; with some extra touches (maybe a more friendly interface) it could probably end up being a package or part of beamer, like \againfigure... –  kccqzy Nov 7 '12 at 17:04
    
@kccqzy: glad to help. I have updated the interface to make it easier to refer to multiple figures in this way. It may or may not be better...! –  cyberSingularity Nov 7 '12 at 17:57
    
Thank you very much for your effort, but there is one caveat: it does not work with overlay specifications. Adding a \pause after \end{figureandsave} would cause LaTeX to complain about the name already defined. If the contents within the figure do not change in different slides, I suppose we could say, e.g., \ifx\expandafter{\csname savedfigure#1box\endcsname}\undefined (haven't tested this yet; decided to procrastinate till tomorrow :p). If we need to address the scenario where contents do change in different slides, the implementation would probably be more complex than necessary... –  kccqzy Nov 7 '12 at 18:54
    
@kccqzy: Changing the \newsavebox to a \newbox is enough to avoid the name already defined error. I have made this change and also separated the concerns in the interface, so the figure can be saved before the first use if desired, though the figureandsave environment is still there too. –  cyberSingularity Nov 7 '12 at 22:31
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.