|
|
|
|
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: |
|
|
|
|
|
- Ordenar-li a
que exporti el projecte:
- Declarar la classe Finestra
(la que conté el mètode main())
com a classe principal:
- 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 és capaç
d'entendre
l'etiqueta <APPLET>,
però,
per alguna raó,
no
pot executar aquest applet."
>
"El vostre navegador
no és pas capaç
d'entendre l'etiqueta
<APPLET>. 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. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
 |