Threads nelle applets.


Java Sun

Earthweb
(ex Gamelan)

Jars

Java Boutique

JavaWorld

PIP






  JSem: 5.4

   Vediamo con un esempio (testo scorrevole) come usare i threads nelle applets.
Come già detto, per creare un thread in un'applet bisogna implementare l'interfaccia Runnable, quindi il nostro codice inizierà con:

public class ScrollingText_1 extends Applet implements Runnable{

Per usare il nostro thread (che si chiama runner) dobbiamo crearlo, chiamare il suo metodo start() affinchè diventi Runnable e scrivere il metodo run() dell'interfaccia Runnable; inoltre sarà opportuno trovare un modo di fermare il thread.
Per fare un testo scorrevole, l'idea è di stampare una stringa (msg) alla posizione x (g.drawString(msg, x, y), y fisso), fare una pausa e ridisegnare la stessa stringa alla posizione (diciamo) x-5; reiterando questo procedimento il testo sfila (da destra a sinistra); rimane da reimpostare le condizioni iniziali quando la scritta è scomparsa completamente (a sinistra) di modo da farla ricomparire (a destra).
Nel metodo paint si stamperà la stringa e nel metodo run del thread si farà variare x.
Ecco il codice completo:

import java.awt.*;
import java.applet.*;

public class ScrollingText_1 extends Applet implements Runnable{

Thread runner;
int msg_pos = -1;
int len;
Font ft = new Font("Monospaced", Font.BOLD, 30);
FontMetrics fm;
int msgH, msgW, charW = 2, w, h, s = 10;
Color bgcol = new Color(0, 0,0);
String msg ="";
Color txtcol = new Color(0,0,255);
Image miaIm;
Graphics m_g;
char[] data = new char[1];

public void init(){
	setBackground(bgcol);
	w = getSize().width;
	h = getSize().height;
	s = Integer.parseInt(getParameter("speed"));
	msg = getParameter("testo");
	if(msg == null){
		msg = "Buon 2001";
	}
	len = msg.length();
	fm = getFontMetrics(ft);
	msgW = fm.stringWidth(msg);
	msgH = fm.getAscent();
	charW = Integer.parseInt(getParameter("scan"));
	miaIm = createImage(w,h);
	m_g = miaIm.getGraphics();
	}

public void paint(Graphics g){
int x=0,y=0;
m_g.setColor(bgcol);
m_g.fillRect(0,0,w,h);
if(msg_pos > 0){
x = w-msg_pos-2;
	for(int i=0; i < len; i++){
	char c = msg.charAt(i);
	data[0] = c; 
	x = w-msg_pos + fm.charWidth(c)+i*25;
	m_g.setFont(ft);
	m_g.setColor(txtcol);
	m_g.drawString(new String(data), x, h/2+msgH/2);
		}
	}
g.drawImage(miaIm,0,0,this);
}

public void start(){
	if(runner == null){
	runner = new Thread(this);
	runner.start();
	}
}

public void stop(){
	if(runner != null){
	runner = null;
	}
}

public void run(){
	Thread thisThread = Thread.currentThread();
	while(runner == thisThread){
		msg_pos += charW;
	if(w - msg_pos + msgW < 0){
	//il msg è scomparso, a sinistra
	msg_pos = 0;}
	repaint();	
	try{
	Thread.sleep(s);
} catch(InterruptedException e){}
	}
}
		
public void update(Graphics g){
	paint(g);
	}
}//fine classe

   Oltre al thread questa applet usa un oggetto FontMetrics, la tecnica del double buffering per evitare il lampeggiamento dello schermo (dovuto al fatto che l'immagine viene ridisegnata troppo spesso) e il passaggio di parametri.
L'oggetto FontMetrics serve a ottenere informazioni sulla font utilizzata (larghezza della stringa, dimensioi dei caratteri ecc... vedere Alcuni semplici effetti grafici e la doc).
Per il double buffering, si rimanda invece alla PIP.
Per il passaggio dei parametri si rimanda anche qui alla PIP, ricordando che il metodo getParameter() della classe Applet ritorna una stringa. I parametri considerati sono: "testo": il messaggio che si vuole visualizzare, "speed" il tempo di pausa del thread e "scan" che è sostanzialmente il passo di avanzamento della stringa.

   Esaminiamo i vari metodi relativi al thread.
Il metodo start():

public void start(){
	if(runner == null){
	runner = new Thread(this);
	runner.start();
}

Il primo start (public void start(){... è il metodo start dell'applet (non del thread), quindi nel metodo start si crea il thread (this si riferisce all'applet) e si chiama il metodo start del thread (runner.start()); questo mette il nostro thread in stato Runnable.

Il metodo run() dell'interfaccia Runnable descrive quello che il thread deve eseguire (essenzialmente spostare la stringa msg, fare una pausa e chiamare repaint()). Il metodo sleep lancia un'eccezione che bisogna catturare.

Il problema è di fermare il thread. La classe Thread ha un metodo stop() ma questo metodo è deprecato, sembra infatti che causi vari problemi, le raccomandazioni della Sun sono di evitare l'uso del metodo stop() della classe Thread (cf doc); quindi per fermare un thread si cercherà di fare terminare il suo metodo run().
L'idea è di combinare la condizione del while del run con il metodo stop() dell'applet (non del thread). Se riguardiamo il metodo run:
Thread thisThread = Thread.currentThread();
while(runner == thisThread){
//codice

vediamo che nel codice successivo non vi è nulla che possa modificare la condizione del while, che quindi sarà sempre verificata. Adesso se la pagina web che ospita la nostra applet viene chiusa o abbandonata, viene chiamato il metodo stop() dell'applet, in questo metodo abbiamo:
if(runner != null){
runner = null;
}
In questo modo la condizione runner == thisThread del while del metodo run non è più verificata e il metodo run del thread termina senza drammi.



 next		content		previous