|
Navegant per un canvas... |
|
|
|
A partir d'aquesta pràctica
introduirem l'ús dels scrollbars
(sí, sí, les barretes verticals i horitzontals que, amb el
ratolí, permeten moure's per una àrea). A més, aprendrem
a fer més coses amb els canvas i
a comprimir tota una aplicació,
amb els seus recursos, en un fitxer
*.jar, que pot arribar a ser autoexecutable! |
|
|
|
Scrollbars |
|
|
|
Pot esdevenir-se que un component (típicament
un canvas) no sigui completament visible
a l'usuari simplement perquè no disposa de prou d'espai i algunes
zones queden ocultes per d'altres components.
La solució estàndard a això és dotar el component
de scrollbars, és a dir de
barres de moviment vertical i/o horitzontal, les quals permeten
navegar per les distintes zones del component.
El paquet java.awt
conté una classe, java.awt.ScrollPane,
que fa tota la feina:
- java.awt.ScrollPane és
un component
i, per tant, pot ser inclòs en el layout
manager de qualsevol contenidor
(per exemple, un frame
o un panel)
- Però també java.awt.ScrollPane
és un contenidor
(container), amb
layout manager null, destinat a rebre
un sol component amb dimensions
pròpies. La part del component que
es fa visible depèn de la posició (decidida per l'usuari!)
dels dos scrollbars que scrollpane
incorpora.
- Si volem construir unl
scrollpane (vegeu-ne la documentació),
disposem de dos mètodes constructors:
- public ScrollPane (),
que el construeix amb la política
(policy)
de mostrar o no els scrollbars
segons si es necessiten o no.
- public ScrollPane (int politica),
que el construeix amb la política
(policy)
definida per int politica,
que és algun d'aquests valors:
- ScrollPane.SCROLLBARS_AS_NEEDED,
- ScrollPane.SCROLLBARS_ALWAYS,
- ScrollPane.SCROLLBARS_NEVER.
- Igual que per a qualsevol contenidor,
per afegir el component
la vista del qual ha de ser comanada pels scrollbars
del scrollpane, el mètode
és public void add(Component component)
|
|
|
|
Ara farem funcionar tot això: posarem
un canvas suficientment gran (900 x 900)
en un scrollpane, posat a la posició
BorderLayout.CENTER d'un frame
més petit que el canvas (600 x 400).
Com sempre, creem el projecte Scrolling
com a "Basic Java Application"
amb el següent codi: |
|
|
|
/*
* @(#)Scrolling.java 1.0 02/10/28
*
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_1\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/ |
|
//package
myprojects.scrolling; |
|
import java.awt.*;
import java.awt.event.*;
class Scrolling extends Frame {
public Scrolling() { //constructor
|
|
ScrollPane
scrollPane=new ScrollPane();
Canvas canvas=new ElMeuCanvas();
canvas.setBackground(new
Color(255,255,200));
canvas.setSize(900,900);
scrollPane.add(canvas);
add(scrollPane,BorderLayout.CENTER); |
|
addWindowListener(new
WindowAdapter() {
public
void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
});
}
public static void main(String args[]) {
System.out.println("Starting
Scrolling...");
Scrolling mainFrame =
new Scrolling();
|
|
mainFrame.setSize(600,
400);
mainFrame.setTitle("Screen
roll"); |
|
mainFrame.setVisible(true);
}
}
|
|
class ElMeuCanvas extends Canvas {
public ElMeuCanvas () { //constructor
super();
}
public void paint (Graphics g) {
Dimension size=getSize();
g.setColor(Color.RED);
g.drawRect(2,2,size.width-4,size.height-4);
g.setColor(Color.BLUE);
for
(int i=5;i<size.width;i=i+30) {
g.drawOval(10,10,i,i);
}
g.setFont(new Font("SansSerif",Font.PLAIN,30));
g.setColor(Color.BLACK);
g.drawString("Mou
els scrollbars!",150,160);
g.drawString("Wapo,
eh?",300,420);
}
}
|
|
|
|
i obtenim això: |
|
|
|
|
|
|
Imatges, fotos, ... |
|
|
 |
Un canvas és
capaç de presentar-nos imatges bitmap
contingudes en fitxers *.gif
o *.jpg. Aquests fitxers
poden residir al propi sistema on s'executa
l'aplicació (fitxers locals) o a
qualsevol node de la xarxa (fitxers
remots), del qual es recuperen mitjançant connexions
TCP/IP. El SDK de Java
té classes i mètodes
per gestionar tot això. |
|
|
|
Fitxers locals: |
|
|
|
- Comencem per imatges
contingudes a fitxers locals. Descarregueu-vos
el fitxer bott_001.jpg
i poseu-lo a la carpeta classes\imatges
del projecte Scrolling. Aquest serà
el fitxer a mostrar.
- És clar que la maquinària que
aconseguirà fer visible
el fitxer depèn del sistema
concret en el qual corre l'aplicació. Cal, doncs, un pont
entre l'AWT i el funcionament efectiu
del nostre sistema. Aquest pont
és la classe java.awt.Toolkit,
als mètodes de la qual s'hi
recorre directament molt poques vegades, però aquesta n'és
una! Començarem per demanar el toolkit
per defecte mitjançant el mètode:
public static Toolkit getDefaultToolkit() |
- Ara ja tenim construït el pont. Demanarem un objecte
java.awt.Image per representar la nostra
imatge amb el mètode
de la classe java.awt.Toolkit:
public Image getImage(String
path_i_nom) |
(Atenció:
la separació entre directoris
ha de ser "/" i no "\")
- I, finalment, només cal dibuixar la imatge
sobre el canvas. El mètode,
de la classe java.awt.Graphics,
és
public abstract
boolean drawImage(Image img,
int
x,int y,
ImageObserver
observer) |
Els paràmetres x
i y són la posició
de l'angle superior esquerre de la imatge
en el canvas i observer
és el propi component sobre
el qual es dibuixa la imatge, en
aquest cas el canvas.
Tot això, posat en el mètode
paint del nostre canvas,
ha de quedar així:
public
void paint (Graphics g) {
Dimension size=getSize(); |
Toolkit
toolkit=Toolkit.getDefaultToolkit();
Image image=toolkit.getImage("imatges/bott_001.jpg"); |
g.setColor(Color.RED);
g.drawRect(2,2,size.width-4,size.height-4);
g.setColor(Color.BLUE);
for
(int i=5;i<size.width;i=i+30) {
g.drawOval(10,10,i,i);
}
g.setFont(new
Font("SansSerif",Font.PLAIN,30));
g.setColor(Color.BLACK);
g.drawString("Mou
els scrollbars!",150,160);
g.drawString("Wapo,
eh?",300,420); |
g.drawImage(image,0,0,this); |
} |
Com era d'esperar, a l'executar el programa, observem que la imatge
tarda una mica en dibuixar-se (s'ha de llegir del disc, tractar-la per
tal de convertir-la a pixels, etc.)
fins que cobreix tot el hi havia al canvas.
Però el procés, tal com està, implica que la Màquina
Virtual intenta dibuixar-la vàries vegades mentre, potser,
encara no és a punt, cosa que es tradueix en desagradables vibracions
del contingut del canvas. Això
també (només faltaria!) té solució. Hi ha
una classe, java.awt.MediaTracker,
que inicia el procés de càrrega i elaboració de
les imatges (Image
getImage(String path_i_nom) no ho fa!) mitjançant
el mètode public
void waitForAll() i informa de que tot està ja llest retornant
true amb el mètode public
boolean checkAll().
Incorporem això al mètode
paint:
public
void paint (Graphics g) {
Dimension size=getSize();
Toolkit toolkit=Toolkit.getDefaultToolkit();
Image image=toolkit.getImage("imatges/bott_001.jpg");
g.setColor(Color.RED);
g.drawRect(2,2,size.width-4,size.height-4);
g.setColor(Color.BLUE);
for
(int i=5;i<size.width;i=i+30) {
g.drawOval(10,10,i,i);
}
g.setFont(new
Font("SansSerif",Font.PLAIN,30));
g.setColor(Color.BLACK);
g.drawString("Mou
els scrollbars!",150,160);
g.drawString("Wapo,
eh?",300,420); |
MediaTracker
mediaTracker=new MediaTracker(this);
mediaTracker.addImage(image,0);
try
{
mediaTracker.waitForAll();
if(mediaTracker.checkAll())
{ |
g.drawImage(image,0,0,this); |
}
}
catch (InterruptedException e) {
System.out.println("No
puc!");
} |
} |
i ara la imatge es carrega de manera ben neta.
La classe, java.awt.MediaTracker
té més mètodes,
els quals permeten controlar la càrrega
simultània de vàries imatges,
tot donant-los identificadors. Us recomanem que per a usos més
sofisticats d'aquesta classe, en llegiu
la documentació amb tota cura.
|
|
Fitxers remots: |
|
|
|
- Per fitxers remots,
la cosa és una miqueta més complicada, la localització
de la imatge (el recurs)
és un URL i, aquí, un
objecte de la classe
java.net.URL (OOP,
gent!). En conseqüència, cal:
- Importar el
paquet java.net:
import java.awt.*;
import java.awt.event.*; |
import java.net.*; |
- Construir
l'URL de la imatge
mitjançant el mètode constructor
public URL(String protocol_adreça)
tenint en compte les excepcions
que llença (vegeu-ne la documentació)
- Construir l'objecte
image amb el mètode
de java.awt.Toolkit, public
Image getImage(URL url).
El mètode paint, ja suprimit
tot allò que després no es veurà, queda així:
public
void paint (Graphics g) {
Dimension size=getSize();
Toolkit toolkit=Toolkit.getDefaultToolkit(); |
URL
url=null;
try
{
url=new
URL(
"http://www.xtec.net/~fie00032/d110m5/fitxers/bigboy.jpg"
);
}
catch (MalformedURLException e) {
System.out.println("No
puc trobar la imatge");
}
Image image=toolkit.getImage(url); |
MediaTracker
mediaTracker=new MediaTracker(this);
mediaTracker.addImage(image,0);
try
{
mediaTracker.waitForAll();
if(mediaTracker.checkAll())
{
g.drawImage(image,0,0,this);
}
}
catch (InterruptedException e) {
System.out.println("No
puc!");
}
} |
i ara, naturalment, la imatge tardarà
força més en dibuixar-se!
|
|
|
|
Fitxers Jar i recursos |
|
|
 |
La penúltima versió de Scrolling,
la que presenta una imatge llegida des
d'un fitxer local, fa servir un
recurs local (el fitxer bott_001.jpg).
Ja sabem que podem unir i comprimir tots
els fitxers *.class
necessaris per a una determinada aplicació en un
únic fitxer *.jar (vegeu la pràctica
3 del mòdul 2). Però
també podem incloure al fitxer
*.jar tots els recursos
necessaris per a l'aplicació, el fitxer
bott_001.jpg en el nostre cas.
Per aconseguir això, cal fer dues coses:
- Canviar la línia
Image image=toolkit.getImage("imatges/bott_001.jpg"); |
per les línies
URL url=getClass().getResource("imatges/bott_001.jpg");
Image image=toolkit.getImage(url); |
- Procurar que, en la construcció del fitxer
*.jar, s'hi inclogui el recurs
imatges/bott_001.jpg: per exemple, l'eina
per a crear fitxers *.jar,
que és jar.exe, executada a la carpeta
classes del projecte,
amb la línia de comanaments:
C:\D110src\D110ws\Modul_5\Scrolling\classes>jar.exe
cvf
Scrolling.jar . |
Es crearà el fitxer
Scrolling.jar, el
qual contindrà tots els fitxers
de la carpeta actual
(el paràmetre
".") i
de les seves subcarpetes,
en particular, tot el contingut de la carpeta
imatges, és
a dir, el fitxer
bott_001.jpg.
|
|
Doncs, som-hi! Fem aquests canvis en el codi i fem el fitxer
Scrolling.jar... I, després, vegem si
tot ha funcionat bé:
- A la carpeta classes
del projecte ha d'haver aparegut el
nou fitxer Scrolling.jar.
- Obrim el fitxer
Scrolling.jar amb WinZip.
L'aspecte ha de ser aquest:
El fitxer bott_001.jpg
ha de figurar amb el path imatges\
i, amb el path meta-inf\,
hi ha d'haver el fitxer Manifest.mf.
D'aquest últim fitxer en parlarem d'aquí una mica.
- Ara traslladem el fitxer
Scrolling.jar a qualsevol altra carpeta
de la nostra màquina i cridem la Màquina
Virtual de Java que executi la nostra aplicació
comprimida amb els seus recursos.
La línia de comanaments és:
c:\On_Sigui>java
-cp Scrolling.jar Scrolling |
Explicació: cridem l'eina
java.exe (la Màquina
Virtual de Java) tot indicant-li que les classes
són (classpath, modificador
-cp) al fitxer Scrolling.jar,
i que la classe principal (la que conté
el mètode main!)
és Scrolling.class. (l'extensió
*.class s'omet)
El resultat ha de ser aquest:
|
|
Naturalment, aquest muntatge serveix per incloure
als fitxers *.jar
tota mena de recursos: imatges, sons, etc.
La clau és a la línia, una mica enigmàtica,
URL url=getClass().getResource("imatges/bott_001.jpg"); |
No entrarem ara a descriure tota la maquinària associada al mètode
public final Class getClass() de la classe
Object (la mare
de totes les classes!). Només
comentar que cal que l'URL creada per getResource
s'ha d'adreçar al mateix lloc d'on ha estat carregada
la classe ElMeuCanvas,
és a dir, el fitxer Scrolling.jar,
i no a cap carpeta del sistema,
i que això ho fa el mètode
getClass().(no pregunteu com!) |
|
|
|
Fitxers Jar autoexecutables |
|
|
 |
El fitxer Manifest.mf
que hi ha a tots els fitxers *.jar
està pensat per posar-hi informacions diverses sobre els paquets,
recursos i/o aplicacions
que guarda. Per exemple, si tornem a obrir, mitjançant WinZip,
el fitxer Scrolling.jar,
i fem doble click sobre Manifest.mf,
en podrem veure el contingut:

Ben poca informació! Aquest fitxer
Manifest.mf és el que l'eina
jar.exe crea per defecte i, com era d'esperar,
no conté res rellevant. Però, si li afegim la línia
Main-Class: Scrolling
llavors conté la informació (ben rellevant, per cert!) sobre
quina és la classe principal,
la que conté el mètode
main (l'extensió
*.class s'omet). El resultat és que,
ara, el nostre fitxer *.jar
és autoexecutable, això
és, el podem cridar directament (fent-hi clic
a sobre, a Windows, per exemple)
i, inmediàtament, l'aplicació
s'executa.
|
|
|
|
El modus operandi és aquest:
- Escriure el fitxer
Manifest.mf amb qualsevol editor
de textos ASCII (el mateix JCreator
és adequat per a això), amb aquest contingut:
i desar-lo fora de l'abast del paràmetre
"." de
jar.exe: un bon
lloc és la carpeta
Scrolling del projecte,
al mateix lloc que els fitxers font *.java.
- A continuació executem
jar.exe a la carpeta classes
del projecte, amb la
línia de comanaments:
C:\D110src\D110ws\Modul_5\Scrolling\classes>jar.exe
cvfm
Scrolling.jar ../Manifest.mf . |
Es crearà el fitxer
Scrolling.jar, el
qual, com abans, contindrà tots
els fitxers de la carpeta
actual (el paràmetre
".") i
de les seves subcarpetes,
és a dir, el fitxer
imatges/bott_001.jpg, però com
que hem afegit el modificador "m",
en lloc de crear un fitxer de manifest per
defecte, ara agafarà com a tal el que acabem de preparar
(el paràmetre "../Manifest.mf")
- Comprovem que tot ha anat bé.
Com abans, obrim el nou fitxer M5p3_01.jar
amb Winzip, mirem si hi són totes les classes
i recursos i, amb doble
click sobre Manifest.mf, en comprovem
el contingut que ara ha de ser:
Ara traslladem el fitxer Scrolling.jar
a qualsevol altra carpeta de
la nostra màquina i, després, simplement amb un doble
click a sobre o, des de la línia
de comanaments,
C:\D110src\D110ws\Modul_5\Scrolling\classes>Scrolling.jar |
o, amb una drecera, ha d'engegar-se
la nostra aplicació, igual que
si es tractés d'un executable
*.exe.
|
|
|
|
JCreator i Jar's |
|
|
 |
Els processos anteriors es poden automatitzar
a JCreator. La successió
Configure -> Options -> Tools ->
Create Jar File
crea l'eina personalitzada per a fer
fitxers *.jar amb manifest
per defecte (és a dir, sense informació rellevant).
Les comandes, creades automàticament
per JCreator, són aquestes:

Segur, però, que convé tenir una altra eina
personalitzada per a crear fitxers
*.jar amb manifest
significatiu. Només cal crear una altra vegada l'eina
i modificar els arguments que JCreator
proposa en aquesta forma:

Llavors, només cal tenir la precaució de situar
el fitxer Manifest.mf
a la carpeta del projecte, per tal que
jar.exe el prengui com a manifest
del fitxer *.jar.
|
|
|
|
|
|
|
 |
|
|
|
|