如何在 Beamer 中将包含大量代码的列表拆分为两个框架

如何在 Beamer 中将包含大量代码的列表拆分为两个框架

我正在设计一张 Python 语言的幻灯片,我想逐步(逐行)展示算法的执行,刷新变量的状态并在任何控制台中模拟输出(模拟调试工具)。

我的问题是,我面临的是一个大型算法,我应该将其拆分成两个或更多个 beamer 框架。我的幻灯片突出显示当前执行的行。因此,我必须在 latex 中设置要着色的框架数和行数。

lstlisting太大(很多行)时,我必须:

  1. 重新lstlisting插入一个新框架(称为“框架 2”);

  2. 设置我想要显示的相同代码的剩余行的范围;

  3. 设置从前一帧的最后一行之后的第一行开始的代码行计数器;

  4. 插入大量命令,突出显示在框架 2 中重新插入的代码片段的行;

这种方式成本太高,而且让我(粗略地)复制前一帧的完整代码。有没有一种方法可以lstlisting只针对一个帧实现,然后 LaTex 会自动将代码拆分到各个帧之间?

下面是我的乳胶代码(lstinputlisting是最重要的部分)。

提前致谢。

\documentclass{beamer}
\usepackage{graphicx,url}
\usepackage[brazil]{babel}   
\usepackage[utf8]{inputenc}
\usepackage{hyperref}

% A CONFIG FILE
\input{config.tex}

\definecolor{ultramarine}{rgb}{0.07, 0.04, 0.56}
\definecolor{ufop-verde}{RGB}{57, 155, 60}

% ALL PACKAGES
\usepackage{graphicx}
\usepackage{verbatim}
\usepackage{floatrow}
\usepackage{sidecap}
\usepackage{scalerel}
\usepackage{listingsutf8}
\usepackage{float}        
\usepackage{pgf, pgffor}
\usepackage{listings}
\usepackage{lstlinebgrd}
\usepackage{tcolorbox}
\usepackage{mdframed}
\usepackage{tabularx}
\usepackage{tikz}
\usepackage{color}
\usepackage{lstlinebgrd}

\newcommand{\numeroaula}{01234}


%% THIS SEQUENCE OS LINES ENABLE THE HIGHLIGHT OF SOURCE CODE INSIDE LSTLISTNGS
\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \btIfInRange{number}{range list}{TRUE}{FALSE}
%
% Test in int number <number> is element of a (comma separated) list of ranges
% (such as: {1,3-5,7,10-12,14}) and processes <TRUE> or <FALSE> respectively

\newcount\bt@rangea
\newcount\bt@rangeb

\newcommand\btIfInRange[2]{%
    \global\let\bt@inrange\@secondoftwo%
    \edef\bt@rangelist{#2}%
    \foreach \range in \bt@rangelist {%
        \afterassignment\bt@getrangeb%
        \bt@rangea=0\range\relax%
        \pgfmathtruncatemacro\result{ ( #1 >= \bt@rangea) && (#1 <= \bt@rangeb) }%
        \ifnum\result=1\relax%
            \breakforeach%
            \global\let\bt@inrange\@firstoftwo%
        \fi%
    }%
    \bt@inrange%
}
\newcommand\bt@getrangeb{%
    \@ifnextchar\relax%
        {\bt@rangeb=\bt@rangea}%
        {\@getrangeb}%
}
\def\@getrangeb-#1\relax{%
    \ifx\relax#1\relax%
        \bt@rangeb=100000%   \maxdimen is too large for pgfmath
    \else%
        \bt@rangeb=#1\relax%
    \fi%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \btLstHL<overlay spec>{range list}
%
% TODO BUG: \btLstHL commands can not yet be accumulated if more than one overlay spec match.
% 
\newcommand<>{\btLstHL}[1]{%
  \only#2{\btIfInRange{\value{lstnumber}}{#1}{\color{orange!25}\def\lst@linebgrdcmd{\color@block}}{\def\lst@linebgrdcmd####1####2####3{}}}%
}%
\makeatother
%% THES SEQUENCE ABOVE ENABLE THE HIGHLIGHT OF SOURCE CODE INSIDE LSTLISTNGS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\batchmode

\usepackage{amsmath,amssymb,enumerate}
\usepackage{epsfig,bbm,calc,color,ifthen,capt-of}

\usetheme{Madrid}
\usecolortheme{senac}

%-------------------------Titulo/Autores/Orientador------------------------------------------------
\title[Comando de decisão IF]{\small{BCC 701 - Programação de Computadores I}\\\LARGE{\textbf{Comando de decisão IF}}}
\date{\dataPT  -  Aula \numeroaula}
\author[DECOM]{Universidade Federal de Ouro Preto - UFOP\\Departamento de Computação - DECOM\\Material Didático Unificado\\\url{www.decom.ufop.br/bcc701}}

%-------------------------Logo na parte de baixo do slide------------------------------------------
\pgfdeclareimage[height=1.0cm]{ufop-logo}{ufop-logo.pdf}
\logo{\pgfuseimage{ufop-logo}\hspace*{0.5cm}}

%-------------------------Este código faz o menuzinho bacana na parte superior do slide------------
\iffalse
\AtBeginSection[]
{
  \begin{frame}<beamer>
    \frametitle{Outline}
    \tableofcontents[currentsection]
  \end{frame}
}
\fi
\beamerdefaultoverlayspecification{<+->}
% ------------------------------------------------------------------------------
\begin{document}
% -----------------------------------------------------------------------------

%---Gerador de Sumário---------------------------------------------------------
\frame{\titlepage}
\section[]{}
\begin{frame}{Sumário}
  \tableofcontents
\end{frame}
%---Fim do Sumário------------------------------------------------------------

% -----------------------------------------------------------------------------
\section{Exemplo (passo a passo)}
\begingroup

    %% THE MOST IMPORTANTE CODE IS BELOW.           <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    %% THE MOST IMPORTANTE CODE IS BELOW.           <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    %% THE MOST IMPORTANTE CODE IS BELOW.           <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    %% THE MOST IMPORTANTE CODE IS BELOW.           <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

%% FRAME 1
 \begin{frame}[fragile]{Exemplo (passo-a-passo)}
\vbox{
    \begin{minipage}[t][0.5\textheight][t]{\textwidth}
        %\lstinputlisting[language=Python, frame=single, linebackgroundcolor={%
        \lstinputlisting[language=Python, firstline=1, lastline=15, firstnumber=1, linebackgroundcolor={% %% HERE I SET MAX OF LINES VISIBLE IN FRAME 1 AND A FIRST NUMBER IN A COLUMN OS LINE COUNTERS
    \btLstHL<1>{1}% on slide 1, highlight lines 1-3
    \btLstHL<2>{2}% on slide 2, highlight lines 6 and 9
    \btLstHL<3,4,5>{4}% on slide 3,4,5, highlight line 4
    \btLstHL<6>{5}}% on slide 6, highlight line 5
  }]{bhaskara.py} %% THIS IS THE PYTHON CODE.
enter code here


% IF THIS PYTHON CODE IS LARGE, I HAVE TO CREATE A NEW FRAME COPYING 
% ALL LATEX CODE POSTED HERE, SET THE LINE WHERE I WANNA START PYTHON CODE 
% AND RECREATE A LIST OF \btLstHL TAGS ABOVE INSERTING THE CORRECT LINES 
% OF A SNIPPET OF CODE

\end{minipage}

    %% THE MOST IMPORTANTE CODE IS ABOVE. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% THE MOST IMPORTANTE SNIPPET IS ABOVE


    \nointerlineskip
    \begin{minipage}[b][0.5\textheight][t]{\textwidth}
        \vspace{0.4in}
        \begin{minipage}[t]{0.55\linewidth}

\end{minipage}\hfill
\begin{minipage}[t]{0.4\linewidth}

\end{minipage}
    \end{minipage}
}

\end{frame}
%% END OF FRAME 1

\endgroup


\end{document}

答案1

因此,您要做的就是在投影仪幻灯片上逐步突出显示代码的所有行,并根据当前行“滚动”代码。这是一个非常简单的解决方案,可以解决这个特定问题(但不太灵活)。

这个想法是有一个\mylisting接受四个参数的命令:

  • 幻灯片编号
  • 要显示的代码的开始和结束行
  • 要突出显示的行号

然后,该命令会使用适当的参数\lstinputlisting在 中插入 。然后,您只需输入要突出显示的行数即可。\only\mylistingframe

在开始时frame,您只需重新定义命令\mycode\mycolor包含要包含的代码和突出显示的颜色。因此,您可以在不同的框架中使用它来显示不同的代码(如果需要)。

对于这个例子,我从中获取了一个示例 Python 代码这里

\documentclass{beamer}
\usetheme{Madrid}

\usepackage{listings}
\usepackage{lstlinebgrd}
\lstset{language=Python, numbers=left, xleftmargin=2em}

\usepackage{filecontents}
\begin{filecontents*}{\jobname.py}
import datetime

now = datetime.datetime.now()

print
print "Current date and time using str method of datetime object:"
print str(now)

print
print "Current date and time using instance attributes:"
print "Current year: %d" % now.year
print "Current month: %d" % now.month
print "Current day: %d" % now.day
print "Current hour: %d" % now.hour
print "Current minute: %d" % now.minute
print "Current second: %d" % now.second
print "Current microsecond: %d" % now.microsecond

print
print "Current date and time using strftime:"
print now.strftime("%Y-%m-%d %H:%M")
\end{filecontents*}

\def\mycode{}
\def\mycolor\color{green}
\def\mylisting<#1>#2#3#4{\only<#1>{\lstinputlisting[firstline=#2, lastline=#3, firstnumber=#2, linebackgroundcolor={\ifnum\value{lstnumber}=#4\mycolor\fi}]{\mycode}}}

\begin{document}

\begin{frame}
    \renewcommand{\mycode}{\jobname.py}
    \renewcommand{\mycolor}{\color{yellow!30!white}}
    \mylisting<1>{1}{15}{1}
    \mylisting<2>{1}{15}{3}
    \mylisting<3>{1}{15}{6}
    \mylisting<4>{5}{20}{10}
    \mylisting<5>{5}{20}{11}
    \mylisting<6>{5}{20}{12}
\end{frame}

\end{document}

在此处输入图片描述

相关内容