Newsgroup: it.comp.java
Titolo: paint su listener javax.swing.Timer

Conversando con Giacomo, è saltato fuori  come implementare la possibilità 
di costruire una linea spezzata (l'es era il cardiogramma).
Sempre tenendo ben presente il cardiogramma ( e quindi a una linea che di 
volta in volta diventa sempre più lunga), avevo pensato di disegnare un 
segmento che partisse dall'estremo del vecchio segmento fino a un nuovo 
punto (non avendo dati in mano, lo genero per il momento con dei numeri 
casuali, presi con java.util.Random).
Per semplicità ho usato, per il momento, un'applet, inserendo un listener 
che "dovrebbe" essere rischiamato da javax.swing.Timer: peccato che in fase 
di debug non sembra mai richiamare il metodo actionPerformed del listener.
Ho provato varie soluzioni (per brevità non le posto tutte), ma non riesco 
mai a fargli disegnare nulla.
Dove sbaglio?
Do lo scheletro del codice:
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.Timer;
public class CardioApplet extends java.applet.Applet
{
   private boolean done;
   private final Point2D oldPoint = new Point2D.Double(0, 100);
   private final Point2D newPoint = new Point2D.Double();
   private double x = 0;
   private Random random ;   
 
   /** Istanzia l'applet CardioApplet */
   public CardioApplet()
   {
      done = false;
      random = new Random();
   }
 
   /** Classe che disegna sulla finestra dell'applet */
   public void paint(Graphics g)
   {
      //cast di g
      final Graphics2D g2 = (Graphics2D) g;
 
      /*CLASSE INTERNA*/
        class Listener implements ActionListener
         {
            public void actionPerformed(ActionEvent e)
            {
               x += 5;
               newPoint.setLocation(x, random.nextInt(200));
               Line2D line = new Line2D.Double(oldPoint,  newPoint);
               g2.draw(line);
               oldPoint.setLocation(newPoint);
            }
         }
        /*FINE CLASSE INTERNA*/
 
        Listener listener = new Listener();      
 
         Timer t = new Timer(1000, listener);
         t.start();
    }
 
}
-- 
Ciao. Fabrizio. ( icq: 241182067 )
< MISTAH KURTZ -- HE DEAD.
                A penny for the Old Guy> 
(T.S. Elliot: the hollow men)

oizirbaF wrote:
'Azz, manca un con: paint su listener *con* javax.swing.Timer.
Ovvio che javax.swing.Timer non sia un listener.


di debug non sembra mai richiamare il metodo actionPerformed del listener.
Non ci siamo... il metodo actionPerformed() del tuo listener viene
chiamato dal thread AWT in corrispondenza di un evento grafico. Se
vuoi forzare la chiamata di actionPerformed() devi andare a trovare la
coda degli event (EventQueue) con
Toolkit.getDefaultToolkit().getSystemEventQueue() e poi richiamare il
suo metodo dispatchEvent();

Maurizio Testa wrote:

Merda .... non sono ancora capace di programmare i thread .... metto a 
riposo il codice per quando sarò in grado di farlo.
Ho cmq capito il senso della cosa, grazie Maurizio.
p.s. c'era magari qlc altro modo per fare la stessa cosa ?


p.s. c'era magari qlc altro modo per fare la stessa cosa ?
Sì, ovviamente. Non sei obbligato a passare per la coda degli eventi
per forzare un repaint. Prova a "studiarti" questo semplice esempio...
import javax.swing.*;
import java.util.*;
public class Clock extends JFrame implements Runnable
{
	JLabel time;
 
	public static void main(String[] args)
	{
		Clock thisApp=new Clock();
	}
 
	Clock()
	{
		this.setTitle("Clock");
		this.setSize(200,50);
		this.setDefaultCloseOperation
			(JFrame.EXIT_ON_CLOSE);
		time=new JLabel();
		this.getContentPane().add(time);
		this.show();
		Thread timer=new Thread(this);
		timer.run();
 
	}
 
	public void run()
	{
		while(true)
		{
			time.setText(""+new Date());
			try
			{
				Thread.sleep(1000L);
			}
			catch(InterruptedException e)
			{
			}
		}
	}
}

cuttone
Ueila , grazie Maurizio.
.... usi i thread cmq ..... 
Ok , ok vado a vedermi il codice. :-)


.... usi i thread cmq ..... 
Beh, te lo ha vietato il dottore o il parroco di usare un misero
thread?

 
Ho parzialmente risolto così: 
CLASSE MAIN:
******************
import javax.swing.*;
import java.util.*;
import java.awt.geom.*;
public class Clock extends JFrame implements Runnable
{
   JLabel time;
   Cardio cardio;
   private int x;
   private Random random;
 
   public static void main(String[] args)
   {
      Clock thisApp=new Clock();
   }
 
 
   Clock()
   {
      random = new Random();
      x = 0;
      this.setTitle("Clock");
      this.setSize(400, 400);
      this.setDefaultCloseOperation
      (JFrame.EXIT_ON_CLOSE);
      cardio = new Cardio();
      this.getContentPane().add(cardio);
      this.show();
      Thread timer=new Thread(this);
      timer.run();
 
   }
 
   public void run()
   {
      while(true)
      {
         x += 5;
         cardio.setPoint(new Point2D.Double(x, random.nextInt(201)));
         cardio.repaint(x-4, 0, x, 400);
         try
         {
            Thread.sleep(100L);
         }
         catch(InterruptedException e)
         {
         }
      }
   }
}
*******************
CLASSE CARDIO:
******************
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
public class Cardio extends JLabel
{
   private Point2D oldPoint;
   private Point2D newPoint;
 
   /** Crea una nuova istanza alla classe Cardio */
   public Cardio()
   {
      oldPoint = new Point2D.Double(10, 10);
      newPoint = new Point2D.Double(10, 10);
   }
 
   public void paint(Graphics g)
   {
      Graphics2D g2 = (Graphics2D) g;
      g2.draw(new Line2D.Double(oldPoint, newPoint));
   }
 
   public void setPoint(Point2D newPoint)
   {
      oldPoint = this.newPoint;
      this.newPoint = newPoint;
   }
 
}
***********************
In verità non risolto tutti i problemi: dovrei aggiustare alcune coordinate 
per evitare piccoli spazi vuoti, inserire uno ScrollBar orrizontale .... , 
ma in fondo quello che volevo era capire come sfruttare eventi su dati in 
tempi reali ..... ho capito che i thread sono strumenti potenti .


Maurizio Testa wrote:

ue ue :-)
La verità è che non li so usare , dammi tempo ... fammi macinare codice.


 ***********************
Č meglio fare l'overridding di paintComponent e non di paint, cioč fare una 
cosa del genere:
 public void paintComponent(Graphics g)
   {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.draw(new Line2D.Double(oldPoint, newPoint));
   }
Infatti, funzia per il rotto della cuffia con una JLabel , ma giŕ con un 
JTextArea va tutto in carte 48 col metodo paint().
Quanto allo srcollbar da inserire, non sono ancora riuscito a risolvere, ma 
appena ci rimetto su gli occhi vedrete che roba !!! :-)


cut
ancora meglio cosě:
 public void paintComponent(Graphics g)
   {
 
      Graphics2D g2 = (Graphics2D) g;
      g2.draw(new Line2D.Double(oldPoint, newPoint));
   }
e poi richiamarlo con un semplice repaint().
