View Full Version : [JAVA] Dubbi su PaintComponent
Micromani
07-04-2010, 14:21
Premetto che sono completamente autodidatta e assolutamente niubbo in materia di programmazione Java, ma dopo ore di sudore su forum, letture e test ho scritto buona parte di un programma che mi ero ripromesso di realizzare.
Il problema che mi blocca è un problema di risorse...
Attualmente all'interno della finestra di interfaccia ho creato un'area dove ho posizionato un elemento ScrollPane e al suo interno ho inserito un jPanel. Ho implementato una nuova classe che estende la jPanel e sovrascritto per essa la PaintComponent.
Meravigliam tutto sembrava funzionare, e in effetti funziona. Ho trovato dei limiti che credo insormontabili, nel senso che per gestire le immagini che voglio visualizzare all'interno del jPanel è stato necessario definire parecchie variabili globali che ne controllano i parametri e all'interno della PaintComponent realizzare i disegni in base a questi parametri.
Mi sono però accorto che questo metodo prende tantissime risorse, la PaintComponent ridisegna continuamente e completamente l'area e non solo "a bisogno" e questo porta la CPU al 100%.
Naturale direte voi...
Ho allora cercato altre strade:
public class Mappa extends JComponent{
[...]
}
public Mappa() {
super();
[...]
}
@Override
public void paintComponent(Graphics g) {
[...]
}
Creando questa classe estensione di JComponent, e caricandola su un jFrame nuovo mi sono accorto che finalmente l'immagine veniva creata una sola volta con indubbio vantaggio in termini di risorse...
private void jButtonDisegnaMouseClicked(java.awt.event.MouseEvent evt) {
JFrame f = new JFrame();
f.setSize(900,900);
f.getContentPane().add (new Mappa());
f.setResizable(false);
f.setVisible(true);
}
Non riesco tuttavia a gestire il PaintComponent all'interno dello ScrollPane contenuto nel Frame principale.
Attualmente il mio Panel è definito:
public class ImagePanel extends JPanel {
non posso però modificarlo facendo estendere a Mappa (che a sua volta estende jComponent perchè mi dice che il tipo non è coerente, e non riesco nemmeno ad usare il metodo ".add", perchè comunque nello scrollPane non appare nulla...
Inoltre avendo "trovato" il codice a giro per la rete non mi è tanto chiaro nemmeno la parte dove utilizzo:
f.getContentPane().add (new Mappa());
il metodo .getContentPane esiste solo per gli oggetti JFrame?
Confido nell'aiuto di chiunque abbia avuto la pazienza di leggermi sicuro che l'iceberg che vedo sulla mia rotta sia solo un ghiacciolino nel drink di alcuni di coloro che mi leggono.
Grazie.
Il getContent pane deriva dal fatto che i componenti di primo livello (le finestre) Swing delegano il contenimento di altri componenti ad un pannello intermedio. Puoi dire sia:
frame.add(qualcosa);
che:
frame.getContentPane().add(qualcosa);
il primo "add" rinvia al secondo, cioè quando dici frame.add lui rimanda a contentPane.add. Questo rinvio è automatico a partire da Java 1.4 (se non ricordo male), prima occorreva essere espliciti e dire sempre frame.getContentPane().add.
Circa il problema dell'estesione singola, puoi risolvere aggiungendo Mappa a ImagePanel:
ImagePanel panel = new ImagePanel();
Mappa mappa = new Mappa();
panel.add(mappa);
l'effetto dipende però dalla corretta definizione del contratto di JComponent in mappa e, sopratutto, dalle necessità: con la composizione ImagePanel non diventa una Mappa, se vuoi questa caratteristica devi usare una composizione con rinvio.
Crei un'interfaccia X con tutti i metodi di Mappa che vuoi che ImagePanel abbia, fai implementare quell'interfaccia a Mappa, fai implementare la stessa interfaccia a ImagePanel, dai a ImagePanel un campo di tipo Mappa (composizione) e per ogni metodo dell'interfaccia X implementato da ImagePanel rimandi al corrispondente metodo di Mappa (rinvio).
La questione più interessante è tuttavia il fatto che il programma consumi il 100% della CPU.
E' possibile che nel paintComponent tu stia invocando direttamente o indirettamente repaint()? Se così fosse avremmo un ciclo eseguito dall'EDT in full load e otterremmo quel 100% della CPU.
In definitiva, che fai di bello in quel paintComponent?
banryu79
07-04-2010, 15:30
Non so gli altri (qui c'è gente veramente in gamba con Java, tipo PGI-bis) però per quanto mi riguarda dalle informazioni contenute nel tuo post non sono riuscito a capire bene la situazione.
Se puoi postare il codice completo delle varie classi coinvolte è meglio.
Poi se ci aggiungi una spiegazione a parole, più organica, di quello che devi realizzare, del problema che devi risolvere e che ti ha spinto a produrre quel codice, e molto meglio.
Per ora ti posto dei link a delle risorse che puoi consultare per formarti una visione di insieme e per capire come utilizzare AWT/Swing per implementare le tue interfacce grafiche:
- The Really Big Index (http://java.sun.com/docs/books/tutorial/reallybigindex.html), casomai non lo conoscessi già, è un ottima fonte di informazioni;
In particolare prova a consultare la sezione: Creating a GUI with JFC/Swing (http://java.sun.com/docs/books/tutorial/uiswing/index.html): trovi tutorial e spiegazioni introduttive a quasi tutti gli aspetti e i componenti della libreria.
In Lesson:Using Swing Components (http://java.sun.com/docs/books/tutorial/uiswing/components/index.html) trovi spiegazioni concernenti alcuni aspetti che hai sollevato nel tuo post; guarda in particolare le due sezioni Using Top-Level Containers (http://java.sun.com/docs/books/tutorial/uiswing/components/toplevel.html) per capire come è strutturrato un frame e The JComponent Class (http://java.sun.com/docs/books/tutorial/uiswing/components/jcomponent.html) per una panoramica su JComponent, che è utile in quanto denominatore comune di tutti i component di Swing (eccetto per i cosidetti "top level containers").
In Lesson: Performing Custom Painting (http://java.sun.com/docs/books/tutorial/uiswing/painting/index.html) c'è una lezione introduttiva al custom painting; un'ottima lettura da affiancargli è il noto articolo Painting in AWT and Swing (http://java.sun.com/products/jfc/tsc/articles/painting/).
C'è anche questo tutorial (http://www.hwupgrade.it/forum/showthread.php?t=2005654), da parte mia consigliatissimo, scritto da un utente del forum (PGI-bis), che è un'ntroduzione breve a Swing.
Inoltre avendo "trovato" il codice a giro per la rete non mi è tanto chiaro nemmeno la parte dove utilizzo:
f.getContentPane().add (new Mappa());
I componenti "aggiunti" a un JFrame vengono infilati nel suo "Content Pane", che è un componente container interno a JFrame (vedi la lezione:"Using Top-Level Containers" per i dettagli).
Questo codice:
frame.add(new Mappa());
e questo codice:
frame.getContentPane().add(new Mappa());
hanno lo stesso effetto: Mappa viene comunque infilata nel content pane di frame, quindi puoi usare tranquillamente la prima versione.
Se posti più codice e spiegazioni forse riesco a darti una mano nello specifico, ciao :)
Micromani
07-04-2010, 17:07
In definitiva, che fai di bello in quel paintComponent?
Temo assolutamente nulla... Nel senso che non ho loop che dovrebbero ripetersi.
Ho notato che su una macchina molto più performante della mia in effetti non va la cpu al 100%; arriva al massimo al 60%, questo di fatto credo escluda il loop infinito, giusto?
La cosa che non capisco, e all'inizio mi ha dato non pochi grattacapi è che se istanzio un ImagePanel e riscrivo il suo metodo paintComponent questi comincia ricorsivamente a disegnarsi; mentre se invoco un nuovo Mappa extension di Jcomponent dentro a un frame questo viene disegnato una sola volta e al limite viene ridisegnato solo se viene ricoperto da un'altra finestra e poi torna sopra.
package wingofwarminiatures;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.*;
import java.io.*;
import javax.swing.*;
import javax.imageio.*;
public class ImagePanel extends JPanel {
private BufferedImage sfondo = null;
private BufferedImage fiamme = null;
private BufferedImage fumo = null;
public void setImage(String immagine) {
System.out.println("carico la mappa nuova");
try {
sfondo = ImageIO.read(getClass().getResource(immagine));
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (IllegalArgumentException iae) {
sfondo = null;
}
}
public ImagePanel() {
super();
try {
sfondo = ImageIO.read(getClass().getResource("campox2.jpg"));
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (IllegalArgumentException iae) {
sfondo = null;
}
}
@Override
public void paintComponent(Graphics g) {
int scala = App.scala;
try {
fiamme = ImageIO.read(getClass().getResource("Fiamme.png"));
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (IllegalArgumentException iae) {
fiamme = null;
}
try {
fumo = ImageIO.read(getClass().getResource("Fumo.png"));
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (IllegalArgumentException iae) {
fumo = null;
}
if (sfondo != null) {
// carica lo sfondo
g.drawImage(sfondo, 0, 0, sfondo.getWidth(), sfondo.getHeight(), this);
this.setSize(sfondo.getWidth(), sfondo.getHeight());
/*
* Inizializzazione componenti
*/
if (App.mappa) {
App.mappa = false;
/*E' stato invocato il cambio di scala tramite rotella del mouse,
quindi va caricato il nuovo sfondo
*/
try {
sfondo = ImageIO.read(getClass().getResource(App.namefile));
this.setSize(sfondo.getWidth(), sfondo.getHeight());
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (IllegalArgumentException iae) {
sfondo = null;
}
}
// Set spessore linee 2
float dash[] = {20.0f};
Graphics2D g2 = (Graphics2D) g;
if (scala == 4) {
g2.setStroke(new BasicStroke(2.0f));
} else if (scala == 2) {
g2.setStroke(new BasicStroke(3.0f));
} else if (scala == 1) {
g2.setStroke(new BasicStroke(4.0f));
}
// Set font scritte
Font font = new Font("Times", Font.ITALIC, 14);
g.setFont(font);
/*
* Disegna aerei
*/
g.setColor(Color.lightGray);
int select = App.shadowSelected;
for (int sh = 0; sh < select; sh++) {
Aereo appo = App.shadow[sh];
// Calcola i vertici e disegna il rettangolo
PointW verticish[] = new PointW[4];
for (int i = 0; i < 4; i++) {
verticish[i] = new PointW();
}
appo.vertici(appo, App.flotta[App.plane].getWidth(),
App.flotta[App.plane].getHeight(),
(float) appo.direzione, verticish);
int xPointssh[] = new int[4];
int yPointssh[] = new int[4];
for (int i = 0; i < 4; i++) {
xPointssh[i] = (int) verticish[i].x / scala * 2;
yPointssh[i] = (int) verticish[i].y / scala * 2;
}
g.drawPolygon(xPointssh, yPointssh, 4);
// Cono
int xsh = (int) App.shadow[sh].getX();
int ysh = (int) App.shadow[sh].getY();
int dirsh = (int) App.shadow[sh].direzione;
double adirsh = App.shadow[sh].direzione * 3.1415 / 180;
double radarmash = App.shadow[sh].antAng * 3.1415 / 180;
// Disegna lato cono
if (App.cono) {
// g.setColor(Color.blue);
int p1x = (int) (xsh + (Math.cos(adirsh - (radarmash / 2)) * App.GITTATA));
int p1y = (int) (ysh - (Math.sin(adirsh - (radarmash / 2)) * App.GITTATA));
g.drawLine(xsh / scala * 2, ysh / scala * 2, p1x / scala * 2, p1y / scala * 2);
int p2x = (int) (xsh + (Math.cos(adirsh + radarmash / 2) * App.GITTATA));
int p2y = (int) (ysh - (Math.sin(adirsh + radarmash / 2) * App.GITTATA));
g.drawLine(xsh / scala * 2, ysh / scala * 2, p2x / scala * 2, p2y / scala * 2);
// Disegna gli archi
g.drawArc(xsh / scala * 2 - App.GITTATA / scala * 2, ysh / scala * 2 - App.GITTATA / scala * 2, App.GITTATA * 2 / scala * 2, App.GITTATA * 2 / scala * 2, (int) (App.shadow[sh].direzione - (App.shadow[sh].antAng / 2)), App.shadow[sh].antAng);
App.GITTATA /= 2;
g.drawArc(xsh / scala * 2 - App.GITTATA / scala * 2, ysh / scala * 2 - App.GITTATA / scala * 2, App.GITTATA * 2 / scala * 2, App.GITTATA * 2 / scala * 2, (int) (App.shadow[sh].direzione - (App.shadow[sh].antAng / 2)), App.shadow[sh].antAng);
App.GITTATA *= 2;
}
}
/*
* Aerei
*/
// i nemici vanno in flotta[1-11]
for (int sh = App.numEnemy; sh >= 0; sh--) {
if (sh == App.plane) {
g.setColor(Color.yellow);
} else if (App.flotta[App.plane].sparaAereo(App.flotta[sh])) {
g.setColor(Color.green);
} else {
g.setColor(Color.red);
}
Aereo appo = App.flotta[sh];
// g.drawString("Enemy " + Integer.toString(sh + 1), (int) appo.getX()/scala*2, (int) appo.getY()/scala*2);
// Calcola i vertici e disegna il rettangolo
PointW verticish[] = new PointW[4];
for (int i = 0; i < 4; i++) {
verticish[i] = new PointW();
}
appo.vertici(appo, appo.getWidth(), appo.getHeight(), (float) appo.direzione, verticish);
int xPointssh[] = new int[4];
int yPointssh[] = new int[4];
for (int i = 0; i < 4; i++) {
xPointssh[i] = (int) verticish[i].x / scala * 2;
yPointssh[i] = (int) verticish[i].y / scala * 2;
}
g.drawPolygon(xPointssh, yPointssh, 4);
// Cono
int xsh = (int) appo.getX();
int ysh = (int) appo.getY();
int dirsh = (int) appo.direzione;
double adirsh = appo.direzione * 3.1415 / 180;
double radarmash = appo.antAng * 3.1415 / 180;
// Disegna lato cono
if (App.cono && App.flotta[sh].antAng > 0) {
// g.setColor(Color.blue);
int p1x = (int) (xsh + (Math.cos(adirsh - (radarmash / 2)) * App.GITTATA));
int p1y = (int) (ysh - (Math.sin(adirsh - (radarmash / 2)) * App.GITTATA));
g.drawLine(xsh / scala * 2, ysh / scala * 2, p1x / scala * 2, p1y / scala * 2);
int p2x = (int) (xsh + (Math.cos(adirsh + radarmash / 2) * App.GITTATA));
int p2y = (int) (ysh - (Math.sin(adirsh + radarmash / 2) * App.GITTATA));
g.drawLine(xsh / scala * 2, ysh / scala * 2, p2x / scala * 2, p2y / scala * 2);
// Disegna gli archi
g.drawArc(xsh / scala * 2 - App.GITTATA / scala * 2,
ysh / scala * 2 - App.GITTATA / scala * 2,
App.GITTATA * 2 / scala * 2,
App.GITTATA * 2 / scala * 2,
(int) (App.flotta[sh].direzione - (App.flotta[sh].antAng / 2)),
App.flotta[sh].antAng);
App.GITTATA /= 2;
g.drawArc(xsh / scala * 2 - App.GITTATA / scala * 2,
ysh / scala * 2 - App.GITTATA / scala * 2,
App.GITTATA * 2 / scala * 2,
App.GITTATA * 2 / scala * 2,
(int) (App.flotta[sh].direzione - (App.flotta[sh].antAng / 2)),
App.flotta[sh].antAng);
App.GITTATA *= 2;
}
// Per ogni aereo carica ombra e disegno
BufferedImage stamp = null;
BufferedImage stampB = null;
try {
stamp = ImageIO.read(getClass().getResource(App.flotta[sh].nameImg));
stampB = ImageIO.read(getClass().getResource(App.flotta[sh].nameSha));
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (IllegalArgumentException iae) {
stamp = null;
stampB = null;
}
// Image test=stamp.getScaledInstance(App.flotta[sh].Weight*App.scala/2, App.flotta[sh].Height*App.scala/2, 1);
// Disegna l'ombra e aereo
// ombra
Graphics2D ombra = (Graphics2D) g.create();
double scalino=0;
switch (App.scala) {
case 2:
scalino = 1;
break;
case 1:
scalino = 2;
break;
case 4:
scalino = (float) 0.5;
break;
}
ombra.translate(appo.getX() * 2 / App.scala
- (stampB.getWidth()*scalino / 2) + scalino*(10 * (App.flotta[sh].livello) + 5),
appo.y * 2 / App.scala
- stampB.getHeight()*scalino / 2 + scalino*(10 * (App.flotta[sh].livello)));
AffineTransform transform = new AffineTransform();
transform.setToScale(scalino, scalino);
transform.rotate(Math.toRadians(-appo.direzione),
stampB.getWidth() / 2, stampB.getHeight() / 2);
ombra.drawImage(stampB, transform, null);
ombra.dispose();
// aereo
Graphics2D aereo = (Graphics2D) g.create();
aereo.translate(App.flotta[sh].getX() * 2 / App.scala
- (stamp.getWidth()*scalino / 2),
App.flotta[sh].y * 2 / App.scala
- stamp.getHeight()*scalino / 2);
transform = new AffineTransform();
transform.setToScale(scalino, scalino);
transform.rotate(Math.toRadians(-App.flotta[sh].direzione),
stamp.getWidth() / 2, stamp.getHeight() / 2);
aereo.drawImage(stamp, transform, null);
aereo.dispose();
}
g.dispose();
g.finalize();
} else {
g.drawString("L'immagine non \u00E0 stata caricata", 100, 100);
}
}
}
I chiarimenti su cosa "dovrebbe" fare il programma sono un pò lunghini e non vorrei farvi perdere troppo tempo, se magari avete qualche attitudine ludica come me magari conoscete il gioco "Wings Of War", e visto che ne sono un appassionato ma anche un padre di famiglia cercavo un modo per poter fare qualche partitella in rete senza dover abbandonare la quiete (per modo di dire) domestica...
Tanto per farsi un'idea sulle meccaniche del gioco:
http://web.me.com/lgradi/kovo2.0/Kovoteca_files/WoWMini-Rulebook_IT_web.pdf
Alla fine ho scoperto che la parte trigonometrica era la più semplice. :doh:
http://img96.imageshack.us/img96/3407/wowbwf.th.jpg (http://img96.imageshack.us/i/wowbwf.jpg/)
Oltre a un consumo esagerato ho notato anche che le carte nello scroll orizzontale in basso (che è fatto allo stesso modo del ImagePanel) tendono a flippare.
In pratica quando seleziono una carta nella parte bassa dello schermo questo compila un vettore di tre carte (le tre mosse da decidere a inizio turno), questo comporta al successivo ridisegnamento delle immagini: per la mappa il disegno del rettangolo grigio, mentre per le carte la sovraimpressione del numero.
Ci sono 2 intoppi.
paintComponent viene invocato potenzialmente un tot di volte dai meccanismi interni di swing. Nel tuo paintComponent accedi al disco fisso per caricare le immagini e siccome i dischi sono lenti come un'agonia l'esecuzione di paintComponent risulta rallentata.
Precarica le immagini, magari nel costruttore: se i file da cui li carichi non cambiano non c'è ragione di accedervi più volte (a meno che non siano immagini abbastanza grandi da mandare in swap la memoria ma non credo).
La questione interessante è il JComponent - JPanel.
Nel paintComponent hai un setSize. Quel setSize causa l'invocazione di un repaint (e quindi di paintComponent) da parte del delegato UI del componente a cui viene assegnata una nuova dimensione.
E qui viene il bello: JPanel ha un delegato UI, JComponent no. Un'estensione di JComponent per la quale non esista un delegato UI, come nel tuo caso, non genera quindi l'invocazione ricorsiva di paintComponent (per via del setSize).
E' strano quel 60%. Forse è un dual-core e va letto come 100% + 20%? Comunque rimuovendo il setSize dal paintComponent e pre-caricando le immagini il problema si risolverà.
Micromani
13-04-2010, 10:45
Ci sono 2 intoppi.
Sei stato gentile!! :p
So che farò rabbrividire qualcuno ma in realtà, non avendo capito la causa del re-paint continuo, non avevo un solo comando repaint in tutto il codice... :stordita:
Il problema adesso è che non so come fare il repaint di un panel (quello della mappa) quando intercetto un evento su un altro panel (quello delle carte).
Se gestisco l'evento mouse del pannello carte posso tranquillamente fare la gestione "classica" e infine un repaint del panel, ma non di un altro.
public class ImagePanel extends JPanel {
private BufferedImage sfondo = null;
private BufferedImage fiamme = null;
private BufferedImage fumo = null;
public void setImage(String immagine) {
try {
sfondo = ImageIO.read(getClass().getResource(immagine));
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (IllegalArgumentException iae) {
sfondo = null;
}
}
public ImagePanel() {
super();
try {
sfondo = ImageIO.read(getClass().getResource("campox2.jpg"));
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (IllegalArgumentException iae) {
sfondo = null;
}
try {
fiamme = ImageIO.read(getClass().getResource("Fiamme.png"));
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (IllegalArgumentException iae) {
fiamme = null;
}
try {
fumo = ImageIO.read(getClass().getResource("Fumo.png"));
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (IllegalArgumentException iae) {
fumo = null;
}
for (int i = 0; i < App.numEnemy; i++) {
try {
App.aerei[i][0] = ImageIO.read(getClass().getResource(App.flotta[i].nameImg));
App.aerei[i][1] = ImageIO.read(getClass().getResource(App.flotta[i].nameSha));
} catch (IOException ex) {
Logger.getLogger(ImagePanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
public void paintComponent(Graphics g) {
/***
questo adesso funziona correttamente
*/
}
Dovendo gestire la "console" dalla finestra in basso con le carte utilizzo il codice:
private void formMouseClicked(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
int indice = evt.getX() / 70;
if (App.shadowSelected < 3) {
if (App.shadowSelected > 0) {
for (int i = 0; i < App.shadowSelected; i++) {
if (indice == App.shadowcard[i]) {
return;
}
}
}
if (App.shadowSelected == 0) {
if (CheckMossa(App.mazzo[indice], App.lastMove)) {
App.mosse[App.shadowSelected] = new Movimento(App.mazzo[indice]);
App.shadow[0] = new Aereo(App.flotta[App.plane], 1);
}
} else {
if (CheckMossa(App.mazzo[indice], App.mosse[App.shadowSelected - 1])) {
App.mosse[App.shadowSelected] = new Movimento(App.mazzo[indice]);
App.shadow[App.shadowSelected] = new Aereo(App.shadow[App.shadowSelected - 1], App.shadowSelected + 1);
}
}
App.shadow[App.shadowSelected].muoviAereo(App.mazzo[indice].getAvanti(), App.mazzo[indice].getDeriva(), App.mazzo[indice].getScosta());
App.shadowcard[App.shadowSelected] = evt.getX() / 70;
App.shadowSelected++;
}
this.repaint();
che fa il repaint della finestra carte ma da cui non so come invocare il repaint della finestra mappa... :help:
Ho provato a fare qualche raggiro, ma per rispetto tralascio...
Dalla finestra di gioco, se metto un pulsante mi permette di fare:
jPanelMappa.repaint();
Help, please..
banryu79
13-04-2010, 12:33
Non puoi passare un riferimento della finestra mappa alla classe ImagePanel?
In questo modo dentro ImagePanel puoi invocare il metodo repaint sulla finestra mappa dentro l'handler che gestisce il click del mouse.
Oppure ImagePanel, al termine della gestione di un click del mouse, potrebbe indicare al suo chiamante (l'oggetto che istanzia e usa ImagePanel) che la mappa va aggiornata [per fare questo ImagePanel ha bisogno di un riferimento al chiamate attraverso il quale eseguire un'invocazione a un metodo del chiamante che aggiorni la mappa [il che a sua volta implica che il chiamante di ImagePanel conosca anche la finestra mappa]].
Però aspetta di sentire PGI, magari ha altri e migliori consigli da darti ;)
Pare anche a me una questione di riferimenti.
Se nel codice della classe A devi poter invocare un metodo di una classe B è necessario che A abbia un riferimento ad un'istanza di B (e non un'istanza qualsiasi ma quella che effettivamente è usata dal resto del programma).
Il "passaggio del riferimento" è banale ma a parole si rischia di generare più confusione che altro.
Alla lontana, se ho due pannelli definiti in due classi:
class PannelloA extends JPanel {
}
class PannelloB extends JPanel {
}
Usati da un terzo componente (in questo caso un JFrame in un main):
public class Main {
public static void main(String[] args) {
//...invokelater
JFrame window = new JFrame();
PannelloA pa = new PannelloA();
PannelloB pb = new PannelloB();
window.add(pa);
window.add(pb, "south");
}
}
E voglio che PannelloB esegua il repaint di PannelloA, si può dare a PannelloA un parametro di tipo PannelloB in costruzione:
class PannelloA extends JPanel {
private PannelloB riferimento;
PannelloA(PannelloB b) {
riferimento = b;
}
}
Poi si va a vedere dove le istanze di PannelloA e PannelloB usate dal programma si "incrociano" e si usa una come parametro dell'istanziazione dell'altra:
public class Main {
public static void main(String[] args) {
//...invokelater
JFrame window = new JFrame();
PannelloB pb = new PannelloB();
PannelloA pa = new PannelloA(pb);
window.add(pa);
window.add(pb, "south");
}
}
A questo punto le due istanze sono "collegate", nel senso che PannelloA ha un riferimento a PannelloB e quindi può invocare i metodi di PannelloB E il riferimento che PannelloA possiede è inizializzato usando quel particolare PannelloB che il programma usa in un certo suo punto.
Naturalmente sono indicazioni di massima, bisogna poi andare a vedere il codice concreto per decidere cosa passare a chi e dove farlo.
Micromani
14-04-2010, 10:03
Perfetto, risolto alla grande.
Grazie al passaggio del riferimento ho risolto.
Complimenti per disponibilità e competenze a tutti!
Grazie a tutti.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.