Mòdul 8

Pràctica 7: Fora de BlueJ  
Tornar presentació tema
Pràctica 6 Pràctica 2 Pràctica 3 Pràctica 4 Pràctica 5 Pràctica 5 Pràctica 1  
     
     
  Executar l'aplicació fora de BlueJ  
     
 

Ara que el Joc de la Vida ja funciona correctament, es tracta d'independitzar-ne l'execució de l'entorn . Això és absolutament imprescindible si, per exemple, vols distribuir l'aplicació a d'altres usuaris! Les tècniques generals per fer això són a la pràctica 5 del mòdul 4. Del Joc de la Vida en faràs una aplicació autònoma i, després, un applet.

 
     
  Una aplicació autònoma:    
     
Convertir el codi que ja tens a una aplicació autònoma és ben fàcil: tal com s'exposa a la pràctica 5 del mòdul 4, només cal que incorporis un mètode  
     
 
    public static void main (String[] args)
 
     
  a la classe Finestra que s'encarregui de crear un objecte Finestra, el qual serà el que veurà l'usuari:  
     
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.Dimension;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

/**
* La classe Finestra és la classe arrel de l'aplicació del Joc
* de la Vida.
*
* @author (el vostre nom)
* @version (un número de versió o la data)
*/
public class Finestra extends JFrame {

    <codi>
     ...
     ...
    <codi anterior>

    /**
     * Estat d'activitat del procés continu.
     */
    boolean esProcesActiu=false;

    /**
     * Mètode main de la classe Finestra.
     */

    public static void main (String[] args) {
        Finestra finestra=new Finestra();
    }

    /**
     * Mètode constructor per a objectes de la classe Finestra.
     */
    public Finestra () { // constructor
        setConfiguracio();
        setControls();

    <etc.>

 
     
Pots provar que tot va bé, tot executant aquest mètode main() de la classe Finestra sense arguments:  
     
 
 
     
 
 
     
  El resultat és el mateix que si, com has fet fins ara, haguéssis construït un objecte Finestra. Observa que el mètode main() l'ha construït pel seu compte i que no el posa pas a la llista d'objectes disponibles!  
     
Ara ja només falta exportar el projecte i fer-ne el fitxer *.jar corresponent. Què cal fer ja està descrit a l'esmentadíssima pràctica 5 del mòdul 4:  
     
 
  1. Ordenar-li a que exporti el projecte:


  2. Declarar la classe Finestra (la que conté el mètode main()) com a classe principal:


  3. Anomenar i desar el fitxer *.jar resultant amb el nom i al lloc de la màquina que et siguin més abellidors...

 
     
  Ara pots anar a la finestra de comanaments del teu sistema, posar-te a la carpeta on hi hagis guardat el fitxer *.jar (posem, com a les figures, C:\java\aplicacions\JocDeLaVida.jar) i executar:  
     
 
 
     
  per tal que s'executi l'aplicació JocDeLaVida.jar.  
     
  En els sistemes Microsoft Windows®, a més, no cal acudir a la finestra de comanaments: només un doble clic sobre la icona del fitxer *.jar és suficient per engegar l'aplicació:  
     
 
 
     
  Un applet    
     
  També, en principi, és senzill convertir l'aplicació de el Joc de la Vida en un applet: La classe principal ja no ha de ser un objecte javax.swing.JFrame, sinó una classe derivada de javax.swing.JApplet, en la qual, el paper del mètode constructor (que ara no hi serà) el fa el mètode public void init() de la classe javax.swing.JApplet. És el propi navegador en el qual s'executi l'applet el que s'encarregarà de construir l'objecte corresponent.  
     
Al projecte JocDeLaVida afegeix-li la classe JocApplet, que no és més que la classe Finestra canviada de nom, derivada de javax.swing.JApplet (que cal importar!), amb supressió dels mètodes main(), setConfiguracio() i inicia(), la transformació del mètode constructor en el mètode init() i la supressió del botó de sortir de l'aplicació, que ara ja no té sentit:  
     
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.Dimension;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

/**
* La classe JocApplet és la classe arrel de l'applet del Joc
* de la Vida.
*
* @author (el vostre nom)
* @version (un número de versió o la data)
*/

public class JocApplet extends JApplet {

    /**
     * L'objecte Mon en el qual viuen i moren els éssers.
     */

    protected Mon mon;

    /**
     * L'objecte MonVisible que fa visibles els éssers
     * del món.
     */

    protected MonVisible monVisible;

    /**
     * Mètode getter per a la variable mon
     * @return el Mon d'aquest JocApplet
     */

    public Mon getMon () {
        return mon;
    }

    /**
     * Mètode getter per a la variable monVisible
     * @return el MonVisible d'aquest JocApplet
     */

    public MonVisible getMonVisible () {
        return monVisible;
    }

    /**
     * Botó "Pas a pas"
     */

    private JButton botoPasAPas;

    /**
     * El procés continu
     */

    private ProcesContinu procesContinu;

    /**
     * Botó pel comanament del procés continu
     */

    private JButton botoProcesContinu;

    /**
     * Etiquetes alternatives pel botó d'engegar i parar el
     * procés continu
     */

    private String[] etiquetes={"Engegar procés continu",
                                "Parar procés continu"};

    /**
     * Estat d'activitat del procés continu.
     */

    boolean esProcesActiu=false;

    /**
     * Mètode init per a applets de la classe JocApplet.
     */

    public void init () {
        setControls();
        mon=new Mon();
        procesContinu=new ProcesContinu(this);
        procesContinu.start();
    }

    /**
     * Mètode que fixa les dimensions del MonVisible.
     * @return les dimensions del MonVisible
     */

    public Dimension getDimensionsMonVisible () {
        int ampleMonVisible=Constants.dimensionsMon.width*
                            Constants.dimensionsEsser.width;
        int alturaMonVisible=Constants.dimensionsMon.height*
                             Constants.dimensionsEsser.height;
        return new Dimension(ampleMonVisible,alturaMonVisible);
    }

    /**
     * Mètode que crea i distribueix els controls d'aquest
     * JocApplet.
     */

    private void setControls () {
        monVisible=new MonVisible(this); // Li passem aquest
                                         // JocApplet com a parà-
                                         // metre

        getContentPane().add(monVisible,
        BorderLayout.CENTER); // El posem a
                              // la posició
                              // CENTER

        JPanel panelBotons=new JPanel(); // Creem el JPanel
        // Col·locació del botó "Pas a pas"
        botoPasAPas=new JButton(); // Creem el botó
        afegeixBoto(botoPasAPas,panelBotons,"Pas a pas",
                    new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        mon.pas();
                        monVisible.repaint();
                    }
                    });
        // Col·locació del botó "Procés continu"
        botoProcesContinu=new JButton(); // Creem el botó
        afegeixBoto(botoProcesContinu,panelBotons,etiquetes[0],
                    new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        esProcesActiu=!esProcesActiu;
                        botoPasAPas.setEnabled(!esProcesActiu);
                        if (esProcesActiu) {
                            botoProcesContinu.setText(etiquetes[1]);
                            procesContinu.setPriority(
                                            Thread.MAX_PRIORITY);
                        } else {
                            botoProcesContinu.setText(etiquetes[0]);
                            procesContinu.setPriority(
                            Thread.MIN_PRIORITY);
                        }
                    }
                    });
        // Col·locació del botó "Extermini". No cal crear-lo abans
        afegeixBoto(panelBotons,"Extermini",
                    new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        mon.ompleMon();
                        monVisible.repaint();
                    }
                    });
        getContentPane().add(panelBotons,         // El posem a
                             BorderLayout.SOUTH); // la posició
                                                  // SOUTH

    }

    /**
     * El procés d'afegir un botó a aquest JocApplet.
     * @param botó que cal afegir.
     * @param contenidor el Container que contindrà el botó.
     * @param text el text que fa d'etiqueta del botó.
     * @param listener l'ActionListener que gestiona els
     * esdeveniments que es generen en el botó
     */

    private void afegeixBoto(JButton boto,
                             JPanel contenidor,
                             String text,
                             ActionListener listener) {
        boto.setText(text);
        boto.addActionListener(listener);
        contenidor.add(boto);
    }

    /**
     * El procés d'afegir un botó a aquest JocApplet.
     * @param contenidor el Container que contindrà el botó.
     * @param text el text que fa d'etiqueta del botó.
     * @param listener l'ActionListener que gestiona els
     * esdeveniments que es generen en el botó
     */

    private void afegeixBoto(JPanel contenidor,
                             String text,
                             ActionListener listener) {
        afegeixBoto(new JButton(),contenidor,text,listener);
    }

}
 
     
  Però ara hi ha un problema: els respectius mètodes constructors de les classes ProcesContinu  
     
 
    public ProcesContinu(Finestra finestra)
 
     
  i MonVisible  
     
 
    public MonVisible(Finestra finestra)
 
     
  esperen un paràmetre de tipus Finestra i no de tipus JocApplet, cosa que fa que el codi de la classe JocApplet no es pugui compilar... Què fer? Es tracta de no duplicar codi innecessàriament i de no perdre la funcionalitat d'aplicació autònoma que ja tenies...  
     
  La solució és definir una nova interfície (interface) que agrupi les classes Finestra i JocApplet sota un únic nom, per exemple AplicacioOApplet i aleshores, substituir totes les variables de tipus Finestra per variables de tipus AplicacioOApplet, sense canviar-ne el nom identificador. Aleshores, només caldrà implementar la interfície AplicacioOApplet a les classes Finestra i JocApplet.  
     
Comença per afegir la interfície AplicacioOApplet al projecte JocDeLaVida, amb aquest codi:  
     
import java.awt.Dimension;

/**
 * La interfície AplicacioOApplet agrupa classes arrel
 * d'aplicacions o d'applets del Joc de la Vida
 * @author (el vostre nom)
 * @version (un número de versió o la data)
 */
public interface AplicacioOApplet {

    /**
     * Mètode getter per a la variable monVisible
     * @return el MonVisible d'aquesta AplicacioOApplet
     */

    public MonVisible getMonVisible();

    /**
     * Mètode getter per a la variable mon
     * @return el Mon d'aquesta AplicacioOApplet
     */

    public Mon getMon();

    /**
     * Mètode que fixa les dimensions del MonVisible.
     * @return les dimensions del MonVisible
     */

    public Dimension getDimensionsMonVisible ();

}

 
     
  La interfície ha de contenir els mètodes que es cridin com a mètodes d'objectes AplicacioOApplet!  
     
  Ara implementa la interfície AplicacioOApplet a les classes Finestra i JocApplet:  
     
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.Dimension;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

/**
* La classe Finestra és la classe arrel de l'aplicació del Joc
* de la Vida.
*
* @author (el vostre nom)
* @version (un número de versió o la data)
*/
public class Finestra extends JFrame implements AplicacioOApplet {

    <codi>
    ...
    ...
    ...
    <codi anterior>

    /**
     * Mètode main de la classe Finestra.
     */

    public static void main (String[] args) {
        AplicacioOApplet finestra=new Finestra();
    }

    <etc>

 
     
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.Dimension;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

/**
* La classe JocApplet és la classe arrel de l'applet del Joc
* de la Vida.
*
* @author (el vostre nom)
* @version (un número de versió o la data)
*/

public class JocApplet extends JApplet implements AplicacioOApplet {

    <etc>

 
     
  i fes els canvis corresponents a les classes ProcesContinu i MonVisible:  
     
/**
 * La classe ProcesContinu representa el procés que resulta de
 * l'encadenament sense solució de continuitat de successius
 * estats del món del "Joc de la Vida".
 *
 * @author (el vostre nom)
 * @version (un número de versió o la data)
 */
public class ProcesContinu extends Thread {

    /**
     * L'AplicacioOApplet en la qual s'esdevé aquest ProcésContinu.
     */

    protected AplicacioOApplet finestra;

    /**
     * Mètode constructor per a objectes de la classe
     * ProcesContinu.
     * @param finestra l'AplicacioOApplet en el qual s'esdevé
     * aquest ProcésContinu.
     */

    public ProcesContinu(AplicacioOApplet finestra) {
// constructor
        this.finestra=finestra;
        setPriority(Thread.MIN_PRIORITY);
    }

    <etc>

 
     
import javax.swing.JPanel;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

/**
* La classe MonVisible representa el panell de visualització d'allò
* que es va esdevenint en el "Joc de la Vida".
*
* @author (el vostre nom)
* @version (un número de versió o la data)
*/
public class MonVisible extends JPanel {

    /**
     * L'AplicacioOApplet que conté aquest MonVisible.
     */

    protected AplicacioOApplet finestra;

    /**
     * Mètode constructor per a objectes de la classe MonVisible.
     * @param finestra L'AplicacioOApplet que conté aquest
     * MonVisible
     */

    public MonVisible(AplicacioOApplet finestra) {
// constructor
        this.finestra=finestra;
        setPreferredSize(finestra.getDimensionsMonVisible());
        MouseAdapter mouseAdapter=new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                MonVisible monVisible=(MonVisible)e.getComponent();

                AplicacioOApplet finestra=monVisible.finestra;
                Mon mon=finestra.getMon();
                int posX=e.getX();
                int posY=e.getY();
                int ampladaEssers=Constants.dimensionsEsser.width;
                int alturaEssers=Constants.dimensionsEsser.height;
                int x=posX/ampladaEssers;
                int y=posY/alturaEssers;

                ...
                ...
                ...

    <etc>
 
     
Ja està! Si no t'has oblidat de res, la compilació és ben neta i ja tens l'applet quasi a punt. Pots provar-lo, encara a , amb l'AppletViewer:  
     
 
 
     
 
 
     
 
 
     
  Pots comprovar que no has perdut la funcionalitat com a aplicació autònoma, tot tornant a executar el mètode main() de la classe Finestra, com feies més amunt.  
     
  Aplicació i applet, tot en un mateix fitxer!    
     
  Ara pots tornar a exportar el projecte, de la mateixa manera que abans, amb el mateix nom pel fitxer *.jar i a la mateixa carpeta. El fitxer JocDeLaVida.jar és, com abans, executable, però ara, si, a la mateixa carpeta on és el fitxer *.jar, hi crees un fitxer HTML com aquest:  
     
 
<HTML>
  <HEAD>
    <TITLE>Applet del Joc de la Vida</TITLE>
  </HEAD>
  <BODY>
    <CENTER>
      <H1>Applet del Joc de la Vida</H1>
      <HR>
      <APPLET CODE="JocApplet.class"
              WIDTH=480
              HEIGHT=360
              ARCHIVE="JocDeLaVida.jar"
              ALT="El vostre navegador &eacute;s capa&ccedil;
                   d'entendre l'etiqueta &lt;APPLET&gt;,
                   per&ograve;, per alguna ra&oacute;,
                   no pot executar aquest applet."
      >
        "El vostre navegador no &eacute;s pas capa&ccedil;
         d'entendre l'etiqueta &lt;APPLET&gt;. Cal actualitzar-lo."
      </APPLET>
      <HR>
    </CENTER>
  </BODY>
</HTML>
 
     
  (digues-li JocApplet.htm, per exemple), aleshores pots executar el fitxer JocDeLaVida.jar com a applet dins de la pàgina web JocApplet.htm.  
     
 
     
     
    Tornar al principi