PDA

View Full Version : [java] Problema in java swing


pimlico
31-05-2005, 09:56
ecco il mio problema: se creo un oggetto swing (es un Jtree, vuoto) e lo attacco a un pannello e visualizzo il frame, quando poi chiamo un altro costruttore con delle strutture per creare il jtree sullo stesso oggetto, il risultato grafico è che vedo sempre il jtree creato all'inizio e non quello con la struttura che voglio far "apparire" io dopo un pò.. in generale il problema è che swing non mi permette delle modifiche dopo che è stato visualizzato il frame. Qualcuno potrebbe spiegarmi come aggirare l'ostacolo.. :help:

fgmac
31-05-2005, 10:57
Non so se ho capito bene, provo ad ipotizzare il pezzo di codice che stai usando
Mi scuso per errori di sintassi, non ho un compilatore sottomano :D


JFrame mioFrame = new ....;
JTree mioTree = new ...;

mioFrame.add(mioTree);

//poi vuoi crearti un tree caricato come vuoi tu
mioTree = new ...;

//questo e' un nuovo tree contenuto in una nuova locazione di memoria
//nel frame rimane quello vecchio




Per i motivi suddetti devi aggiungere il tree solo dopo averlo costruito come vuoi tu.


Spero di aver azzeccato la tua problematica.

ciao,

pimlico
31-05-2005, 12:29
esatto, il problema è proprio quello.. infatti vorrei sapere se c'è un modo di aggirare l'ostacolo, ossia di far apparire al posto del jtree che c'è in un momento un altro jtree creato successivamente, senza dover distruggere il frame e ricrearlo.. cioè se esiste il modo di dire a java di "aggiornare" un elemento grafico.

cmq grazie per la risp!!

3nigma666
31-05-2005, 13:25
come ben saprai la funzione ke disegna in un pannello con le swing (ma anche con le awt è il metodo:

paintComponet(Graphics g)

questo metodo è un metodo automatizzato con il quale tu NON PUOI interaggire!
nel metodo paintComponent devi solo scrivere il codice relativo agli oggetti ke vuoi disegnare.Per spiegarmi meglio posto come esempio il codice del mio Pacman:



public class Panels extends JPanel
{

public Panels()
{

//inizializzi qua i tuoi oggetti assegnando loro coordinate iniziali ecc ecc

}

public void paintComponent (Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
//setBackground(Color.WHITE);
int imageWidth = 20;
int imageHeight = 20;
next = mappa.testa;
//Disegno la mappa
Rectangle2D map = new Rectangle2D.Double(mappa.leftX(),mappa.topY(),mappa.width(),mappa.height());
g2.setPaint(Color.BLACK);
g2.fill(map);
g2.draw(map);

for (int k=0;k<14;k++){
next = (Muro) next;
Rectangle2D wall = new Rectangle2D.Double(next.leftX(),next.topY(),next.width(),next.height());
g2.setPaint(Color.BLUE);
g2.fill(wall);
g2.draw(wall);
next = next.succ();
}

//Disegno PacMan
g2.drawImage(pacman.image(),pacman.leftX(),pacman.topY(),null);

g2.drawString("Created by Valerio Bignardi",20,20);
g2.drawImage(fantasmino.image(),fantasmino.leftX(),fantasmino.topY(),null);
g2.drawImage(fantasmino.image(),fantasmino2.leftX(),fantasmino2.topY(),null);
g2.drawImage(ball.image(),ball.leftX(),ball.topY(),null);
g2.drawString("Life:",10,40);
int h = 0;
for (k = pacman.Life();k>0;k--){
g2.drawImage(image2,0,50 + (h * 50),null);
h++;
}
}//End paintComponent

//....

}


Quello ke tu devi fare è creare una classe Frame dove all interno richiami il costruttore della classe Panels.richiamando il costruttore della classe Panels automaticamente viene richiamata la classe paintComponent ogni qual volta deve essere ridisegnata la finestra (Esempio: se tu ridimensioni con il mouse la finestra, viene richiamato il metodo paintComponent per ridisegnare,o se magari copri la finestra interessata con un altra).
Visto ke gli oggetti ke tu disegni sono mutabili nel tempo,ovverosia cambiano stato e posizione nel tempo (come nel mio caso) sarai tu a dover richiamare la funzione paintComponent ogni qualvolta c'è stato un cambiamento nel disegno e questo avviene tramite la funzione :
repaint(int x,int y,int width,int height) dove x e y solo l'angolo alto a sx del frame ,mentre width e hegiht sono la larghezza e l'altezza del frame.Quindi per esempio se hai una finestra di 800 x 600 farai: repaint(0,0,800,600) se devi ridisegnare tutta la finestra.Se invece devi ridisegnare solo magari la meta inferiore fai: repaint(400,300,800,600).
Capito?
è molto semplice! grazie alla funzionalita ke da la programamzione ad oggetti,tu non devi preoccuparti di scrivere in paintComponent tutte le possibili casistiche e richiamarle opportunamente,ma ti basta fare come ho fatto io:
infatti per quanto riguarda pacman non scrivo in paintComponent tutte le possibili coordinate ke puo assumere pacman durante il gioco,ma bensi invoco il metodo leftX() e topY() ke restituiscono di volta in volta le coordinate esatte di quel momento.
Spero di essere stato chiaro!

3NiGm@666

fgmac
31-05-2005, 13:50
Scusa ma non capisco. :muro:
Perche' non puoi sostituire il tree con quello che costruisci?
o perche' non puoi lavorare su quello che hai aggiunto al frame?
perche' te ne devi creare uno nuovo apposta?


ciao,

3nigma666
31-05-2005, 14:24
Non mi sono spiegato bene .

Saro piu sintetico e ti scrivo dello pseudo codice moooolto alla buona giusto per farti capire


---------------> Tree.java
public class Tree
{
public Tree()
{
// costruisco il mio albero iniziale
}

public void Modifica_tree()
{
//modifica il tuo albero
}

public int x()
{
//ritorna i valore dell albero necessari per essere disegnato
}
public int y()
{
//ritorna i valore dell albero necessari per essere disegnato
}
public int width()
{
//ritorna i valore dell albero necessari per essere disegnato
}
public int height()
{
//ritorna i valore dell albero necessari per essere disegnato
}

public Tree tree_succ()
{
//restituisce l'elemento successivo dell'albero
}
}

------------> Panels.java

public class Panels extends JPanel
{
private Tree tree;
public Panels()
{
Tree tree = new Tree();
Threadtree Ttree = new Threadtree(); //Thread Necessario per far partire la logica di modifica dell'albero
Ttree.start(); //Faccio partire il Thread che richiama all'interno il metodo per modificare l'albero
//e altre inizializzazioni del caso
//..
//...

}

paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int k;
//----------------- DISEGNO L'ALBERO----------------------------
do
{
Rectangle2D rect = Rectangle2D.Double(tree.x(),tree.y(),tree.width(),tree.height());
g2.draw(rect);
tree = tree.succ(); //assegno a tree l'elemento successivo
}while (tree != null ) //o qualsiasi altro parametro tu abbia usato per identificare la fine dell'albero
}//End paintComponent

private class ThreadTree extends Thread
{
public ThreadTree() {}

public void run()
{
do
{
tree.Modifica_tree()
repaint(0,0,800,600);
//MEtto in pausa il while ogni 100 ms ,in questa maniera do a paintComponent il tempo di ridisegnare la scena

try{
Thread.sleep(100); //mette in pausa il processo il while sostanzialmente per 100 ms
}catch (InterruptedException e)
{
System.out.println(e);
}
}while (finite le modifiche)
}//End ThreadTree

}//End class Panels

---------------> TreeFrame.java

public class TreeFrame extends JFrame
{
// instance variables - replace the example below with your own

public TreeFrame()
{
setTitle("Tree");
setSize(800,600);
Panels panel = new Panels();
getContentPane().add(panel);//o se hia JAva 5.0 basta fare: add(panel);
}


------------->DrawFrame.java
public class DrawFrame extends JFrame
{
public DrawFrame()
{

}

public static void main (String[] args)
{
TreeFrame frame = new TreeFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}


Se non dovesse esserti chiaro con lo pseudo codice,ti spiego brevemente.

Classe DrawFrame : crea il tuo frame
Classe TreeFrame : aggiunge al frame il pannello
Classe Panels : si occupa di disegnare l albero
Classe ThreadTree: si occupa di creare un nuovo processo ke gestisce le modifiche dell'albero
Classe Tree : si occupa di tutta la logica dell'albero modifiche creazione ecc..

Spero ke ora sia chiaro :muro:
:D

pimlico
31-05-2005, 16:55
scusami ma nn riesco ad utilizzare i tuoi metodi.. anche perchè sto modificando un codice già creato e quindi nn ho molta libertà di modificare..
però dimmi se sbaglio (..e sbaglio perchè non funziona!!):
io ho creato un Jframe con un Jpanel e vari componenti all'interno, tra i quali un Jtree
JTree cartella=new JTree();
scroll = new JScrollPane(cartella);
centrale.add(scroll); //centrale è il pannello

poi alla pressione di un tasto il JTree deve "popolarsi":

DefaultTreeModel tree = getMyListModel(lista); //questo è un metodo mio che fornisce il DefaultTreeModel, e funziona perchè posso creare JTree come dico io, purchè lo faccia con il costruttore: JTree cartella=new JTree(lista);
cartella.setModel(tree);
repaint(); //sono in una classe che estende JFrame

ora così facendo passo dal vedere un JTree di default, creato dal costruttore senza argomenti, a uno che nn visualizza niente!! :cry:

3nigma666
31-05-2005, 18:06
non mi avevi parlato della pressione dei tasti.se devi premere un tasto per far si ke il tutto venga modificato,il discorso cambia!
Inanzittuto elimina il thread ke ti facevo creare io ed implementa in questo modo la mia classe Panels:

public class Panels extends JPanel implements KeyListener
{
//..

public void keyPressed (KeyEvent event) {
keyCode = event.getKeyCode();
Tree.modifica_tree(keyCode)
repaint (0,0,800,600);
} //End KeyPressed

public void keyTyped(KeyEvent e) { }

public void keyReleased(KeyEvent e) { }
} //end Panels


//MODIFICA ANCHE IN QUESTA MANIERA IL METODO MODIFICA_TREE()

public class Tree
{
//...
public void modifica_tree(int KeyCode)
{
//KeyCode è un valore int ke viene assegnato a seconda del tasto
// premuto dalla tastiera,in quanto ad ogni tasto della tastiera viene
// assegnato un numero intero.
//quindi a seconda del tasto premuto fai fare una azione (ora non so
//ke tasti hai scelto tu e ke interazione abbiano)
// PEr sapere ke valore ha un tasto della tastiera fai un nel metodo
//precedente keyPressed un: System.out.println(keyCode);

switch (KeyCode)
{
case 37:
//...
case 38:
//....
}
}







in questo modo associ alla classe Panels (ke è quella ke si occupa d disegnare) un "ascoltatore" di eventi,ovverosia ogni qual volta ke venga premuto un tasto della tastiera ,viene richiamato il codice presente nel metodo keyPressed,Viene qindi richiamato "Teoricamente" infinite volte,tante quante le volte ke l'utente preme un tasto.
;)
ok?

quindi fondamentalmente devi fare cosi nel tuo codice:

Inanzittutto nel costruttore lascia SOLO E RIBADISCO SOLO il codice relativo alla creazione dell'albero di default.
Crea un metodo Modifica albero nella tua classe tree
aggiungi l'interfaccia keyListener nella tua classe ke disegna il pannello (scrivendo: implements keyListener)
in questa maniera aggiungi un ascoltatore al tuo oggetto Pannello
ORa crea nella classe pannello i seguenti metodi:

public void keyPressed (KeyEvent event) {
keyCode = event.getKeyCode();
Tree.modifica_tree(keyCode)
repaint (0,0,800,600);
} //End KeyPressed

public void keyTyped(KeyEvent e) { }

public void keyReleased(KeyEvent e) { }

e come puopi vedere dal codice richiama la funzione modifica_tree appena creata nella funzione keyPRessed e vedrai ke ogni volta ke premi il tasto avvera cio ke vuoi !!

;) :sofico:

3nigma666
31-05-2005, 18:31
importa questi:


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

ti serviranno