Beginning Sistemas de Información Java Botones Listado siguiente
PresentaciónEntrada/SalidaBibliotecasSwingMarcosBotonesCuadros de texto
ListasImágenesMenúsDiálogosArchivosGráficos 2D 

Botones
El componente JButton se cuenta entre los más utilizados de Swing. Permite desencadenar la ejecución de un método llamado actionPerformed() cuando el usuario hace clic en el botón o pulsa la combinación de teclas aso. Este método se encuentra en una clase derivada de ActionListener que se asocia al botón mediante una llamada al método addActionListener(). Como dato curioso, los botones y las opciones de menú (JMenuItem) funcionan exactamente igual; no es de extrañar pues se encuentran en la misma jerarquía de herencia.

Como ejemplo, vamos a crear una botonera. Cada uno de los botones corresponde a uno de los tipos de letra instalados en nuestro ordenador. Cuando el usuario hace clic en un botón, el texto de la parte superior de la pantalla se escribe con el tipo de letra asociado al botón.

Botones de Font

Se ha utilizado un JScrollPane para garantizar que sea posible visualizar todos los botones necesarios, independientemente de su número, que va a ser relativamente elevado si nuestro sistema tiene instalado un gran número de tipos de letra. De hecho, el tiempo de ejecución del programa puede elevarse si el número de tipos de letra es grande, debido a la notable cantidad de memoria necesaria.

La primera clase que se muestra es ManejoBotones, un derivado de ActionListener
/*
	Esta es la clase que contiene el método actionPerformed()
	que se invoca cuando el usuario hace clic en un botón
*/
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.Font;

public class ManejoBotones implements ActionListener {
	JLabel pantalla;
	Font[] fuente;
	ManejoBotones(JLabel p, Font[] f) {
		pantalla = p;
		fuente = f;
	}
	public void actionPerformed(ActionEvent e) {
		int num_fuente = Integer.parseInt(e.getActionCommand());
		pantalla.setText("ABCDEFGHIJKLMN—OPQRSTUVWXYZ "+fuente[num_fuente].getFontName());
		pantalla.setFont(fuente[num_fuente]);
	}
}

Y esta otra clase es la que prepara todo, y se encarga de crear los botones, dándoles como nombre el tipo de letra deseado, tras haber solicitado al sistema operativo la lista total de tipos instalados.
//
// BotonesDeFont.java
//

import javax.swing.JButton;
import javax.swing.BorderFactory;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;

public class BotonesDeFont extends JFrame2 {
 private int num_fonts;
 private JPanel botones;
 private JScrollPane cuadricula;
 private JLabel pantalla;
 private Font[] f;
 private String[] nombres;
 private ManejoBotones mb;
 BotonesDeFont() {
 super("BotonesDeFont");
 
 try {
  UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName() );
  }
 catch(Exception e)
  {
  System.out.println(e);
  };
 
 f = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
 num_fonts = f.length;
 botones = new JPanel(new GridLayout(0,3), false);
 pantalla = new JLabel("Haga clic en un botón");
 pantalla.setPreferredSize(new Dimension(850, 50));
 pantalla.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
 botones.setBorder(BorderFactory.createEmptyBorder(10,10,10,20));
 mb = new ManejoBotones(pantalla, f);

 JButton[] b = new JButton[num_fonts];
 for(int i=0;i<num_fonts;i++)
  {
  f[i] = f[i].deriveFont(17.0f);// Ojo... un int sería el estilo!
  b[i] = new JButton(f[i].getFontName());
  b[i].setActionCommand(i+"");
  b[i].addActionListener(mb);
  botones.add(b[i]);
  }
 cuadricula = new JScrollPane(botones);
 getContentPane().add(cuadricula, BorderLayout.CENTER);
 getContentPane() .add(pantalla, BorderLayout.NORTH);
 pack();
 setVisible(true);
 }
  
 public static void main(String args[]) {
 new BotonesDeFont();
 }
}

Estas dos clases hacen uso de JFrame2, que se puede ver a continuación:

import javax.swing.JFrame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;


public class JFrame2 extends JFrame{
  JFrame2() {
    super("Sin t‚tulo");
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent we) {
        System.exit(0);
      }
    });
  } // Constructor sin argumentos
  JFrame2(String t) {
    super(t);
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent we) {
        System.exit(0);
      }
    });
  } // Constructor con argumentos
}

Este ejemplo muestra la forma en que funcionan los botones en Swing: una vez creado el botón con su nombre, se le asigna un ActionListener y se añade el botón a un contenedor, en el cual quedará ubicado en función del Layout asociado previamente al contenedor. Es fácil crear una disposición rectangular o botonera.

Ejercicio.- Construir una calculadora elemental, dotada de las cuatro reglas aritméticas (de momento, sin memoria). Conviene dibujar previamente una máquina de estados; de lo contrario el programa se vuelve bastante complejo.

Una calculadora
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Toolkit;
import javax.swing.border.EmptyBorder;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

public class Calcu01 extends JPanel implements ActionListener {
 // Interfaz de usuario
 private String[] n = { "1", "2", "3", "+",
    "4", "5", "6", "-",
    "7", "8", "9", "*",
    "0", "C", "=", "/"};
 private JButton[] b = new JButton[n.length];
 private JLabel pantalla = null;
 private JPanel botonera = new JPanel(new GridLayout(4,4));
 private Font f = new Font("Serif", Font.BOLD, 18);
 private EmptyBorder borde_botonera, borde_pantalla;
 // Programa
 // Estados
 final int LEER_1  = 1;
 final int LEER_2  = 2;
 final int MOSTRAR  = 3;
 // Tipos de botón pulsado
 final int ES_NUM  = 1;
 final int ES_OP   = 2;
 final int ES_C   = 3;
 final int ES_IGUAL  = 4;
 private String str1="0";
 private long num1=0, num2=0, resultado = 0;
 int estado;
 char operacion;
 Calcu01() {
  // Interfaz de usuario
  setLayout(new BorderLayout());
  pantalla = new JLabel("0.0", SwingConstants.RIGHT);
  pantalla.setFont(f);
  for(int i=0;i<n.length;i++)
   {
    b[i] = new JButton(n[i]);
    b[i].addActionListener(this);
    b[i].setActionCommand(n[i]);
    b[i].setFont(f);
    botonera.add(b[i]);
   }
  borde_botonera = (EmptyBorder)BorderFactory.createEmptyBorder(15,15,15,15);
  borde_pantalla = (EmptyBorder)BorderFactory.createEmptyBorder(15,15,0,15);
  botonera.setBorder(borde_botonera);
  pantalla.setBorder(borde_pantalla);
  add(botonera, BorderLayout.CENTER);
  add(pantalla, BorderLayout.NORTH);
  // Funcionamiento
  estado = LEER_1;
 }// Constructor
 // Método auxiliar
 int tipo_boton(char letra) {
  if (Character.isDigit(letra))
   return ES_NUM;
  else if ("+-*/".indexOf(letra) != -1)
   return ES_OP;
  else if (letra == 'C')
   return ES_C;
  else return ES_IGUAL;
 }
 public void actionPerformed(ActionEvent ae) {
  char letra = ae.getActionCommand().charAt(0);
  int tb = tipo_boton(letra);
  switch(estado) {
  case LEER_1:
   {
    switch(tb) {
     case ES_NUM: if (str1=="0")
        str1 = "" + letra;
       else
        str1 = str1 + letra;
       pantalla.setText(str1);
       break;
     case ES_C: str1 = "0";
       pantalla.setText(str1);
       break;
     case ES_IGUAL: Toolkit.getDefaultToolkit().beep();
       break;
     case ES_OP: operacion = letra;
       num1 = Long.parseLong(str1);
       str1 = "0";
       estado = LEER_2;
       break;
    } // switch(tb),LEER_1
    break;
   }// LEER_1
  case LEER_2:
   {
    switch(tb) {
     case ES_NUM: if (str1=="0")
        str1 = "" + letra;
       else
        str1 = str1 + letra;
       pantalla.setText(str1);
       break;
     case ES_C:  str1 = "0";
       pantalla.setText(str1);
       break;
     case ES_OP:  Toolkit.getDefaultToolkit().beep();
       break;
     case ES_IGUAL: num2 = Long.parseLong(str1);
       switch(operacion) {
        case '+':resultado = num1+num2;break;
        case '*':resultado = num1*num2;break;
        case '-':resultado = num1-num2;break;
        case '/':resultado = num1/num2;break;
       }
       pantalla.setText(Long.toString(resultado));
       estado = MOSTRAR;
       break;
    } // switch(tb),LEER_2
    break;
   }// LEER_2
  case MOSTRAR:
   {
    switch(tb) {
     case ES_NUM: str1 = "" + letra;
      pantalla.setText(str1);
      estado = LEER_1;
      break;
     case ES_C:  str1 = "0";
      pantalla.setText(str1);
      break;
     case ES_OP:
     case ES_IGUAL: Toolkit.getDefaultToolkit().beep();
      break;
     } // switch(tb),MOSTRAR
     break;
   }// MOSTRAR
  } // switch(estado)
 }
}

Este programa se basa, como se ha dicho, en una máquina de estados. Cuando arranca la calculadora, está dispuesta para recibir lo que será el primer operando. No se pasa al segundo estado mientra el usuario no pulse en una tecla de función (+, -, *, /). Una vez hecho esto estamos en un segundo estado, de lectura del segundo operando, en el que se permanece mientras el usuario no pulse el signo =. Entonces se vuelve al estado 1, preparado para un nuevo número.
En cuanto al programa principal, que está basado en JFrame2 (q.v.), puede ser el siguiente:
//
//  Calculadora.java
//


public class Calculadora extends JFrame2 {
    public Calculadora() {
  super("Calculadora");
  Calcu01 c01 = new Calcu01();
        setContentPane(c01);
        pack();
        setVisible(true);
    }
    
    public static void main(String args[]) {
  new Calculadora();
    }
}


Ejercicio.- Construir un programa que muestre una frase sencilla en pantalla. Mediante casillas de verificación (botones de radio más bien) el programa nos permitirá controlar el tipo de letra empleado, activando y desactivando los botones correspondientes.

botonesderadio.jpg

import javax.swing.border.EmptyBorder;
import javax.swing.ButtonGroup;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class PanelBotonesDeRadio extends JPanel implements ActionListener {
  /*
    Atributos de la clase
  */
  JLabel pantalla;
  String[] nombre_fuente = {  "Dialog", "DialogInput", "Monospaced",
          "Serif", "SansSerif", "Symbol"};
  int casos = nombre_fuente.length;
  Font[] f = new Font[casos];
  JRadioButton[] jr = new JRadioButton[casos];
  ButtonGroup bg = new ButtonGroup();
  JPanel botonera = new JPanel(new GridLayout(0,2));
  EmptyBorder e = new EmptyBorder(10,10,10,10);
  EmptyBorder ep = new EmptyBorder(0,10,0,10);
  /*
    Constructor
  */
  PanelBotonesDeRadio(JLabel p) {
    pantalla = p;
    for(int i=0; i<casos; i++)
      {
        f[i] = new Font(nombre_fuente[i], Font.PLAIN, 18);
        jr[i] = new JRadioButton(f[i].getFontName(),false);
        jr[i].setActionCommand(i+"");
        jr[i].addActionListener(this);
        bg.add(jr[i]);
        botonera.add(jr[i]);
      }
    
    botonera.setBorder(e);
    pantalla.setBorder(ep);

    pantalla.setFont(f[0]);
    jr[0].setSelected(true);
    setLayout(new BorderLayout());
    add(pantalla, BorderLayout.CENTER);
    add(botonera, BorderLayout.WEST);
    setPreferredSize(new Dimension(700,200));
  }
  /*
    Implementación de ActionListener
  */
  public void actionPerformed(ActionEvent e) {
    pantalla.setFont(f[Integer.parseInt(e.getActionCommand())]);
  }
}
En cuanto al programa principal, puede ser similar al que se ve a continuación. Una vez más, se basa en JFrame2, ya visto y que no repetimos.
/** 
 * PruebaBotonesDeRadio.java
 *
 * Description: 
 * @author      coti
 * @version     1.0
 */

import javax.swing.JLabel;

public class PruebaBotonesDeRadio extends JFrame2{
  public PruebaBotonesDeRadio() {
    JLabel texto = new JLabel("Jovencillo emponzoñado de whisky");
    PanelBotonesDeRadio pbdr = new PanelBotonesDeRadio(texto);
    getContentPane().add(pbdr);
    pack();
    setVisible(true);
  }

  static public void main(String[] args) {
    new PruebaBotonesDeRadio();
  }
  
}

Ejercicio.- Como ejemplo del manejo (un tanto especial) de casillas de verificación, considérese el grupo siguiente. Como se observará, la casilla PLAIN desactiva a las otras dos. Las casillas BOLD e ITALIC pueden estar activadas o desactivadas de forma independiente entre si, generándose siempre el tipo de letra correcto. No se trata, por tanto, de un grupo de botones de radio puro, no tampoco de un grupo de casillas de verificación puro. Hemos ampliado el comportamiento habitual de la interfaz gráfica de usuario, en una forma correcta porque el comportamiento es el esperado por el usuario. El programa está basado en las clases que se muestran a continuación.

casillas de verificación
//
//  CDV.java
//

import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.border.EmptyBorder;

public class CDV extends JPanel {
    static public final int PLAIN = 0, BOLD = 1, ITALIC = 2, BOLDITALIC=3;
    String[] estilo = {"Font.PLAIN", "Font.BOLD", "Font.ITALIC"};
    int num_cdv = estilo.length;
    int i;
    JCheckBox[] jc = new JCheckBox[num_cdv];
    JPanel panel_botones = new JPanel(new GridLayout(0,1));
    JLabel texto = new JLabel("Jovencito emponzoñado de whisky");
    Font[] f = {  new Font("Courier", Font.PLAIN, 18),
                    new Font("Courier", Font.BOLD, 18),
                    new Font("Courier", Font.ITALIC, 18),
                    new Font("Courier", Font.BOLD+Font.ITALIC, 18) };
    ManejoCheckBox[] mb = new ManejoCheckBox[num_cdv];
    EmptyBorder eb = (EmptyBorder)BorderFactory.createEmptyBorder(20,20,20,20);
    CDV() {
        super();
        panel_botones.setBorder(eb);
        for(i=0;i<num_cdv;i++)
            {
                jc[i] = new JCheckBox(estilo[i], false);
                panel_botones.add(jc[i]);
            }
        texto.setPreferredSize(new Dimension(400,100));
        texto.setBorder(eb);
        texto.setFont(f[0]);

        for(i=0;i<num_cdv;i++)
          {
            mb[i] = new ManejoCheckBox(jc, texto, f, i);
              jc[i].addItemListener(mb[i]);
            }
        add(panel_botones, BorderLayout.WEST);
        add(texto, BorderLayout.CENTER);
   }
}

//
//  PruebaCDV2.java
//

import java.awt.*;

public class PruebaCDV2 extends JFrame2 {
    public PruebaCDV2() {
    super("PruebaCDV2");
    getContentPane().add(new CDV());
        pack();
        setVisible(true);
    }
    
    public static void main(String args[]) {
      new PruebaCDV2();
    }
}

//
//  ManejoCheckBox.java
//

import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import javax.swing.BorderFactory;
import javax.swing.border.EmptyBorder;

public class ManejoCheckBox implements ItemListener {
  private JCheckBox[] casillas;
  private JLabel pantalla;
  Font[] fuente;
  int num_casilla;
  ManejoCheckBox(JCheckBox[] jc, JLabel tx, Font[] ff, int nc) {
            casillas = jc;
            pantalla = tx;
            fuente = ff;
            num_casilla = nc;
        }
  public void itemStateChanged(ItemEvent e) {
            boolean isPlain = casillas[CDV.PLAIN].isSelected();
      boolean isBold = casillas[CDV.BOLD].isSelected();
            boolean isItalic = casillas[CDV.ITALIC].isSelected();
            boolean activacion = (e.getStateChange()==ItemEvent.SELECTED);
      switch(num_casilla) {
        case CDV.PLAIN: {
                  if(activacion)
                    {
                      casillas[CDV.BOLD].setSelected(false);
                      casillas[CDV.ITALIC].setSelected(false);
                      pantalla.setFont(fuente[CDV.PLAIN]);
                    }
                  else
                    {
                    };
                  break;
                }
        case CDV.BOLD:  {
                  if (activacion)
                    {
                      casillas[CDV.PLAIN].setSelected(false);
                      if(isItalic)
                        pantalla.setFont(fuente[CDV.BOLDITALIC]);
                      else
                        pantalla.setFont(fuente[CDV.BOLD]);
                    }
                  else //ItemEvent.DESELECTED
                    {
                      if(!isItalic)
                        {
                          casillas[CDV.PLAIN].setSelected(true);
                          pantalla.setFont(fuente[CDV.PLAIN]);
                        }
                      else
                        {
                          casillas[CDV.PLAIN].setSelected(false);
                          pantalla.setFont(fuente[CDV.PLAIN]);
                        }
                    };
                  break;
                }
        case CDV.ITALIC:  {
                  if (activacion)
                    {
                      casillas[CDV.PLAIN].setSelected(false);
                      if(isBold)
                        pantalla.setFont(fuente[CDV.BOLDITALIC]);
                      else
                        pantalla.setFont(fuente[CDV.ITALIC]);
                    }
                  else //ItemEvent.DESELECTED
                    {
                      if(!isBold)
                        {
                          casillas[CDV.PLAIN].setSelected(true);
                          pantalla.setFont(fuente[CDV.PLAIN]);
                        }
                      else
                        {
                          casillas[CDV.PLAIN].setSelected(false);
                          pantalla.setFont(fuente[CDV.BOLD]);
                        }
                    };
                  break;
                }
      };

        }
}

Como curiosidad, obsérvese que estamos detectando los cambios de estado de una casilla de verificación, con objeto de forzar el cambio de fuente cuando el usuario hace clic en el botón que denota PLAIN, ITALIC o BOLD. Obsérvese también el mecanismode selección de estilo, basado en sumar los "estilos" que aporta en forma de constantes la clase Font.

Ejercicio.- Crear un combo que permita seleccionar cualquier tipo de letra instalado en el sistema. Al seleccionar una opción del combo, el programa modificará el tipo de letra de una frase mostrada en pantalla. Este ejercicio es similar similar a la prueba de botones de fonts; al utilizar un combo, resulta mucho más compacto. Las clases que forman parte del programa pueden verse a continuación:
Prueba
/** 
 * PruebaCombo.java
 *
 * Description: 
 * @author      coti
 * @version     1.1
 */
  import javax.swing.JButton;
  import javax.swing.BorderFactory;
  import javax.swing.border.EmptyBorder;
  import javax.swing.JLabel;
  import javax.swing.JPanel;
  import javax.swing.JScrollPane;
  import javax.swing.UIManager;
  import java.awt.Cursor;
  import java.awt.Dimension;
  import java.awt.Font;
  import java.awt.BorderLayout;
  import java.awt.GridLayout;
  import java.awt.GraphicsEnvironment;
  import java.awt.Toolkit;


public class PruebaCombo extends JFrame2 {
  PruebaCombo() {
    super("Lista desplegable");
    Dimension dim_pantalla, dim_cuadro;
    int posx, posy; // Vamos a centrar el JFrame en la panalla.
    JLabel pantalla = new JLabel("Qué figurota exhibe :");
    PanelCombo pc = new PanelCombo(pantalla);
    getContentPane().add(pc);
    dim_pantalla = Toolkit.getDefaultToolkit().getScreenSize();
    dim_cuadro = pc.getPreferredSize();
    pack();
    setLocation(  (dim_pantalla.width-dim_cuadro.width)/2,
            (dim_pantalla.height-dim_cuadro.height)/2);
    setCursor(Cursor.getDefaultCursor());
    setVisible(true);
  }

  static public void main(String[] args) {
    new PruebaCombo();
  }
  
}
//
// PanelCombo.java
//

import javax.swing.border.EmptyBorder;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.BorderLayout;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Arrays;

public class PanelCombo extends JPanel
            implements ActionListener {
  private JLabel pantalla;
    private Font[] f;
    private String[] nombre;
    private int num_fonts;
    private JComboBox combo;
    private String texto_viejo;
  PanelCombo(JLabel p) {
    /*
      Preparamos un listado de todas las fuentes
      presentes en el sistema, con sus nombres.
      Como getAllFonts() proporciona Font de tamaño
      1, derivamos otro de tamaño 18.
    */
        f = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
        num_fonts = f.length;
        for(int i=0;i<num_fonts;i++)
          f[i] = f[i].deriveFont(18.0f);
        nombre = new String[num_fonts];
        for(int i=0;i<num_fonts;i++)
          nombre[i] = f[i].getFontName();
        
    pantalla = p;
    pantalla.setPreferredSize(new Dimension(500,40));
    EmptyBorder borde_pantalla = (EmptyBorder)BorderFactory.createEmptyBorder(10,10,10,10);
        pantalla.setBorder(borde_pantalla);
        pantalla.setFont(f[0]);
        texto_viejo = pantalla.getText();
        pantalla.setText(texto_viejo + f[0].getFontName());

    EmptyBorder borde_combo = (EmptyBorder)BorderFactory.createEmptyBorder(10,10,10,10);
        combo = new JComboBox(nombre);
        combo.setBorder(borde_combo);
        combo.setSelectedIndex(0);
        combo.addActionListener(this);
        /*
          Atención a esta adición
        */
        combo.setEditable(true);
        /*
          Fin de la adición
        */
    setLayout(new BorderLayout());
        add(combo,BorderLayout.WEST);
        add(pantalla, BorderLayout.CENTER);
        
  }
  public void actionPerformed(ActionEvent e) {
    JComboBox c = (JComboBox)e.getSource();
    String font_seleccionado = (String)c.getSelectedItem();
    int num_font = Arrays.binarySearch(nombre, font_seleccionado);
    /*
      Esto es necesario: sólo se admiten nombres de Font
      exactos (respetando mayúsculas y minúsculas).
    */
    if (num_font >=0 )
      {
        pantalla.setFont(f[num_font]);
        pantalla.setText(texto_viejo + f[num_font].getFontName());
      }
    else
      Toolkit.getDefaultToolkit().beep();
    /*
      Fin de la modificación
    */
  }
}

Ejercicios propuestos

1.- La calculadora que se muestra más arriba tiene limitaciones evidentes. Se pide construir un programa similar, dotando a la calculadora de los conocidos botones M+, M-, MR y MC (añadir a memoria, restar de memoria, recordar memoria y borrar memoria, respectivamente). Obsérvese que es preciso modificar la maquina de estados para tener en cuenta las nuevas posibilidades ofrecidas por la memoria. En la imagen se muestra una calculadora con memoria.

2.Sería posible añadir una "cinta de papel" a la calculadora anterior? Véase la imagen adjunta. Sin demasiado esfuerzo, se puede construir una calculadora dotada de cinta; a fin de cuentas basta con registrar cada operación en un JTextArea. Otra cosa es construir una calculadora avanzada, con más funciones y posibilidades.
 Quizá el lector quiera dedicar un rato agradable a pensar en la máquina de estados de la calculadura cuya imagen se ve a la derecha. La función 2nd hace que aparezcan las funciones trigonométicas e hiperbólicas inversas en las posiciones homólogas del teclado.
4.-Rizando el rizo... ¿sería muy difícil tomar nota de las teclas pulsadas por el usuario? Y una vez conocidas las teclas, sería muy difícil reproducir la sucesión de teclas pulsadas? Esto es, ¿se puede grabar un programa? ¿Se puede reproducir? ¿Se puede crear una calculadora programable? Sólo falta añadir variables al asunto y se dispondrá de una herramienta muy flexible...
5.-Se pide construir un entorno trivial de ejecución para programas escritos en una versión muy simplificada de BASIC. El entorno debe ofrecer botones para las posibilidades de Abrir (cargar un programa de disco), Ejecutar (un programa previamente cargado o escrito a mano), Guardar (el programa en un archivo de disco) y Salir. El "lenguaje" puede contar con las primitivas input, print y let, y los cuatro operadores aritméticos elementales. Las variables, que pueden ser únicamente numéricas o alfanuméricas, necesitan ser declaradas previamente. El bucle for-next es opcional,aunque interesante (el contador de programa pasa a ser el número de línea, no es complicado). Tómese como ejemplo la versión de BASIC denominada Chipmunk Basic, que se hallará aquí