Visualizzazione dei risultati da 1 a 3 su 3
  1. #1

    problema painting swing...

    Salve a tutti,

    sto avendo non pochi problemi nella realizzazione del painting con la libreria swing...vi posto un pò di codice per arrivare subito al punto:

    codice:
    public class Campo extends JPanel{
    
    private Casella[][] caselle = new Casella[Commons.NUM_RIGHE][Commons.NUM_COLONNE];
    
    public Campo(){
    super(); 		
    this.setLayout(new GridLayout(Commons.NUM_RIGHE, Commons.NUM_COLONNE)); 		
    
    for(int i=0;i<Commons.NUM_RIGHE;i++){
    for(int j=0;j<Commons.NUM_COLONNE;j++){
    Casella tmp = new Casella(i,j);
    tmp.setVisible(true);
    this.add(tmp);
    caselle[i][j] = tmp;
    } 		
    } 	
    } 	 	
    public void paintComponent(Graphics g){
    super.paintComponent(g);
    //setBackground(Color.BLACK);
    }
    }
    codice:
    public class Casella extends JLabel{  	
    private int x;
    private int y;
    
    public Casella(int x,int y){
    this.x = x;
    this.y = y;
    }
    
    public void paintComponent(Graphics g){ 
    super.paintComponent(g);	
    Graphics2D g2d = (Graphics2D) g; 		 //setBorder(BorderFactory.createLineBorder(Color.black));
    g2d.fill(new Rectangle(this.x, this.y, this.getWidth(), this.getHeight())); 	g2d.drawString(this.x + "," + this.y,this.getWidth()/2,this.getHeight()/2);
    } }
    In pratica voglio realizzare una scacchiera che poi evolverà in qualcosa di diverso e per farlo ho creato una mia estensione di JPanel in cui ho un array di caselle, che sono a loro volta estensioni di JPanel, tengo inoltre il riferimento alle varie caselle tramite l'array caselle[][]...

    detto questo ho qualche problemino con il metodo paintComponent:
    in Campo chiamo il metodo della superclasse, che quindi chiama automaticamente il paintComponent di tutte le caselle che compongono il campo (giusto?)

    quindi sovrascrivo paintComponent della singola casella, e qui vorrei semplicemente (per ora) disegnare i bordi di tale casella. Non posso usare setBorder(BorderFactory.createLineBorder(Color.bla ck)); perchè poi in realtà campo sarà un thread che ad ogni "passo" fa muovere i vari elementi sullo schermo e chiama il repaint del pannello stesso. Ora poichè la sleep del thread sarà molto breve (nell'ordine dei 20 ms) usando il metodo setBorder ottengo lo sfarfallio delle linee che compongono i bordi (e anche qui non ho capito perchè, immagino che la chiamata al metodo statico createLineBorder sia piuttosto lenta). Allora disegno direttamente il rettangolo del frame ma quello che ottengo è che alcune linee non sono disegnate ed altre invece si. Come mai ?

    Per ora ho questi dubbi di base che non mi consentono di andare avanti...se qualcuno ha voglia di darmi una mano lo ringrazio anticipatamente !

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: problema painting swing...

    Originariamente inviato da camellight
    ho creato una mia estensione di JPanel in cui ho un array di caselle, che sono a loro volta estensioni di JPanel
    Ok, questa comunque è una delle soluzioni.

    Originariamente inviato da camellight
    detto questo ho qualche problemino con il metodo paintComponent:
    in Campo chiamo il metodo della superclasse, che quindi chiama automaticamente il paintComponent di tutte le caselle che compongono il campo (giusto?)
    No, a dire il vero il paintComponent si occupa solo del contenuto "grafico" del componente ... non dei componenti figli. Il painting dei componenti "figli" (quelli contenuti) è fatto in una fase successiva al paintComponent. La spiegazione è in:

    A Closer Look at the Paint Mechanism

    E tra l'altro (e a meno ci siano necessità davvero particolari) un componente come JPanel generalmente lo si usa o solo come "contenitore" di altri componenti o solo come "superficie grafica" per farci del custom painting. Di norma o l'uno o l'altro, raramente entrambi.

    Originariamente inviato da camellight
    quindi sovrascrivo paintComponent della singola casella, e qui vorrei semplicemente (per ora) disegnare i bordi di tale casella. Non posso usare setBorder(BorderFactory.createLineBorder(Color.bla ck)); perchè poi in realtà campo sarà un thread che ad ogni "passo" fa muovere i vari elementi sullo schermo e chiama il repaint del pannello stesso. Ora poichè la sleep del thread sarà molto breve (nell'ordine dei 20 ms) usando il metodo setBorder ottengo lo sfarfallio delle linee che compongono i bordi (e anche qui non ho capito perchè, immagino che la chiamata al metodo statico createLineBorder sia piuttosto lenta). Allora disegno direttamente il rettangolo del frame ma quello che ottengo è che alcune linee non sono disegnate ed altre invece si. Come mai ?
    Ma il bordo, se deve restare di un certo tipo per molto tempo/sempre, basta invocare setBorder 1 volta sola .... mica tutti i momenti.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Eccomi di nuovo con un altro problema...innanzitutto volevo ringraziare andbin per la risposta precisa e ovviamente corretta...ho letto il link sul meccanismo del painting ed ho capito un pò meglio come funziona...inoltre ovviamente il bordo è una proprietà che va impostata una volta sola ... ora modificando leggermente la classe precedente ho creato questa:

    codice:
    public class Casella extends JPanel{  	
    private boolean occupata; 	
    private int i; 	
    private int j; 	
    private int numero = -1;  	
    
    public Casella(int i, int j){ 		
    this.i = i; 		
    this.j = j;  		
    if(i == 0 || i == Commons.NUM_RIGHE - 1){ 			setBorder(BorderFactory.createLineBorder(Color.black)); 		
    } 	
    }  	
    
    public void paintComponent(Graphics g){ 		
    super.paintComponent(g); 		
    Graphics2D g2d = (Graphics2D) g;  		
    ArrayList<Scia> scie = Campo.getScie(); 		
    for(int i=0;i<scie.size();i++){ 			
    Scia tmp = scie.get(i); 			
    if(tmp.getX() == this.i && tmp.getY() == this.j){
    //g2d.drawImage(tmp.getImage(),this.getWidth()/4,this.getHeight()/4,this.getWidth() / 2,this.getHeight() / 2,null);
    //g2d.drawLine(this.getWidth() /2, 0, this.getWidth() /2, this.getHeight());
     				 				
    if(tmp.getVerso() == Verso.SOPRA){ 					g2d.setColor(Color.BLUE);
     					g2d.drawLine(this.getWidth() /2, 0, this.getWidth() /2, this.getHeight() / 2);
     				} 				
    else if(tmp.getVerso() == Verso.SOTTO){ 					g2d.setColor(Color.RED); 					
    g2d.drawLine(this.getWidth() /2 , this.getHeight() /2 ,this.getWidth() / 2 , this.getHeight() ); 				
    } 				
    else if(tmp.getVerso() == Verso.DESTRA){ 					if(tmp.isSciaPari()) 						g2d.setColor(Color.BLUE); 					else 						g2d.setColor(Color.RED); 					 					g2d.drawLine(this.getWidth() / 2 , this.getHeight() / 2 , this.getWidth(), this.getHeight() / 2); 				
    } 				
    else if(tmp.getVerso() == Verso.SINISTRA){ 					if(tmp.isSciaPari()) 						g2d.setColor(Color.BLUE); 					
    else 						
    g2d.setColor(Color.RED); 					
    g2d.drawLine(this.getWidth() / 2, this.getHeight() / 2, 0 , this.getHeight() / 2); 				
    } 			
    } 		
    } 	
    }//altri metodi get & set
    }
    tuttavia a volte capita che (soprattutto mandando in esecuzione contemporaneamente più volte lo stesso programma) venga lanciata una eccezione di questo tipo :

    codice:
    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 	at Casella.paintComponent(Casella.java:33) 	at javax.swing.JComponent.paint(Unknown Source) 	at javax.swing.JComponent.paintChildren(Unknown Source) 	at javax.swing.JComponent.paint(Unknown Source) 	at javax.swing.JComponent.paintToOffscreen(Unknown Source) 	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source) 	at javax.swing.RepaintManager$PaintManager.paint(Unknown Source) 	at javax.swing.RepaintManager.paint(Unknown Source) 	at javax.swing.JComponent._paintImmediately(Unknown Source) 	at javax.swing.JComponent.paintImmediately(Unknown Source) 	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 	at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source) 	at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source) 	at java.awt.event.InvocationEvent.dispatch(Unknown Source) 	at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 	at java.awt.EventQueue.access$000(Unknown Source) 	at java.awt.EventQueue$1.run(Unknown Source) 	at java.awt.EventQueue$1.run(Unknown Source) 	at java.security.AccessController.doPrivileged(Native Method) 	at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) 	at java.awt.EventQueue.dispatchEvent(Unknown Source) 	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 	at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 	at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 	at java.awt.EventDispatchThread.run(Unknown Source)
    ora a quanto ho capito dovrebbe essere un problema dovuto al fatto che il thread EDT esegue a volte alcuni metodi in un ordine tale che alcuni oggetti sui quali si va ad operare ancora non sono stati creati, da cui la NullPointerException...facendo un semplice controllo (oggetto!=null in pratica) si possono "saltare" una o più chiamate al paintComponent fino a quando gli oggetti necessari non siano stati effettivamente creati...ora in questo caso non riesco a capire quale sia l'oggetto nullo. L'eccezione è lanciata a questa riga :

    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at Casella.paintComponent(Casella.java:33)
    ovvero
    if(tmp.getX() == this.i && tmp.getY() == this.j){...}

    ma cos'è nulla ? la casella ? E come risolvo, mettendo all'inizio di paintComponent un if(this==null) return; ???

    Grazie in anticipo e scusate per il post lunghissimo !

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.