View Full Version : [Java] Confronto tra icone e icone di bottoni (Campo Minato)
Simone89RN
15-07-2009, 10:38
Ciao a tutti, sto progettando un applicazione che gestisca il gioco del Campo Minato e per il sistema di gioco sono ormai arrivato a concluderlo, mi serve il vostro aiuto per risolvere l'ultimo problema legato alla costruzione dei numeri che segnalano le mine confinanti.
Purtroppo non ho ancora generato il Javadoc e quindi il codice non è ancora commentato, quindi vi spiego qui tutti i vari campi e metodi delle classi in esame.
Questa è la classe progettata per gestire il sistema del gioco:
package campoMinato;
import java.util.Random;
import javax.swing.*;
import componenti.*;
public class MyGameSystem {
private JButton [][] game;
private int rows, cols, mines, row, col, index;
private Random newrow, newcol;
private GenericComponent component;
public MyGameSystem(JButton [][] game, int rows, int cols, int mines) {
this.game = game;
this.rows = rows;
this.cols = cols;
this.mines = mines;
newrow = new Random();
newcol = new Random();
}
public void CreateGame() {
for (index = 0; index < mines; index++) {
row = newrow.nextInt(rows);
col = newcol.nextInt(cols);
CreateMines(row,col);
}
CreateNumbers();
}
public void CreateMines(int r, int c) {
if (game[r][c].getDisabledIcon() == null) {
component = new MineComponent("Icone/j9.gif");
game[r][c].setDisabledIcon(component.getIcon());
} else {
index--;
}
}
public void CreateNumbers() {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (game[i][j].getDisabledIcon() == null) {
int n_mines = CountMines(i,j);
switch (n_mines) {
case 0: {
component = new NumberComponent("Icone/j0.gif");
game[i][j].setDisabledIcon(component.getIcon());
break;
}
case 1: {
component = new NumberComponent("Icone/j1.gif");
game[i][j].setDisabledIcon(component.getIcon());
break;
}
case 2: {
component = new NumberComponent("Icone/j2.gif");
game[i][j].setDisabledIcon(component.getIcon());
break;
}
case 3: {
component = new NumberComponent("Icone/j3.gif");
game[i][j].setDisabledIcon(component.getIcon());
break;
}
case 4: {
component = new NumberComponent("Icone/j4.gif");
game[i][j].setDisabledIcon(component.getIcon());
break;
}
case 5: {
component = new NumberComponent("Icone/j5.gif");
game[i][j].setDisabledIcon(component.getIcon());
break;
}
case 6: {
component = new NumberComponent("Icone/j6.gif");
game[i][j].setDisabledIcon(component.getIcon());
break;
}
case 7: {
component = new NumberComponent("Icone/j7.gif");
game[i][j].setDisabledIcon(component.getIcon());
break;
}
case 8: {
component = new NumberComponent("Icone/j8.gif");
game[i][j].setDisabledIcon(component.getIcon());
break;
}
}
}
}
}
}
public int CountMines(int r, int c) {
int n_mines = 0;
for (int i = r-1; i <= r+1; i++) {
for (int j = c-1; j <= c+1; j++) {
if (((i >= 0) && (j >= 0)) && ((i < rows) && (j < cols))) {
if (game[i][j].getDisabledIcon() == null)
n_mines++;
}
}
}
return n_mines;
}
}
Campi:
game: Matrice di bottoni che rappresenta la griglia di gioco.
rows: Intero che rappresenta il numero di righe di game.
cols: Intero che rappresenta il numero di colonne di game.
mines: Intero che rappresenta le mine che verranno inserite in game.
row: Intero che rappresenta una riga generata a caso.
col: Intero che rappresenta una colonna generata a caso.
index: Intero che dice a runtime quante mine sono gia state create in game.
newrow: Oggetto di classe Random che genererà una riga.
newcol: Oggetto di classe Random che genererà una colonna.
component: Oggetto che crea all'occorrenza l'icona mina o numero.
Metodi:
MyGameSystem() : Costruttore della classe.
void CreateGame(): Metodo pubblico che crea il sistema di gioco utilizzando i metodi CreateMines() e CreateNumbers(). Il compito principale del metodo è quello di creare righe e colonne a caso nella griglia dove verranno inserite inanzitutto le mine.
void CreateMines(): Metodo (pubblico) che utilizza come parametri gli interi rappresentanti la riga e colonna generati in CreateGame() per creare e inserire in griglia le mine (icona del bottone disabilitato).
void CreateNumbers(): Metodo (pubblico) che una volta messe le mine in griglia si occupa di inserire nelle caselle rimaste i numeri (icona del bottone disabilitato) corrispondenti alle mine confinanti. Viene utilizzato il metodo intero CountMines() per contare queste mine confinanti e a seconda del valore restituito creare l'icona giusta da settare ai bottoni.
int CountMines(): QUI STA IL MIO PROBLEMA Metodo intero (pubblico) che passati come parametri una riga e una colonna di un bottone, inizia un controllo nella griglia sulle 8 caselle confinanti al bottone, tralasciando le caselle con riga e colonna negative oppure fuori dai limiti della matrice. Questo metodo dovrebbe riconoscere SOLO l'icona mina e incrementare la variabile corrispondente alle mine confinanti da restituire, ma INVECE riconosce qualsiasi casella in cui sia stata gia settata l'icona del bottone disabilitato.
So che l'errore è alla riga: if (game[i][j].getDisabledIcon() == null)
perchè debbuggando in Eclipse mi entra e quindi incrementa la variabile anche quando trova un icona numero, quindi ho cercato di togliere il null e di confrontare l'icona del bottone disabilitato con l'icona della mina, ma il risultato non è stato quello aspettato, anzi è stato peggiorativo perchè non riconosceva nemmeno più le mine.
Dunque in pratica, dovrei confrontare l'icona del bottone disabilitato con quella della mina che dovrebbero risultare uguali e invece non lo sono. C'è qualcuno che può aiutarmi?
Spero di essere stato chiaro nell'esporvi il codice, se avete bisogno di migliori spiegazioni oppure anche delle classi GenericComponent, MineComponent, NumberComponent, ditelo che li posto tranquillamente.
malocchio
15-07-2009, 11:38
Ciao a tutti, sto progettando un applicazione che gestisca il gioco del Campo Minato e per il sistema di gioco sono ormai arrivato a concluderlo, mi serve il vostro aiuto per risolvere l'ultimo problema legato alla costruzione dei numeri che segnalano le mine confinanti.
Purtroppo non ho ancora generato il Javadoc e quindi il codice non è ancora commentato, quindi vi spiego qui tutti i vari campi e metodi delle classi in esame.
Questa è la classe progettata per gestire il sistema del gioco:
[CUT]
Campi:
game: Matrice di bottoni che rappresenta la griglia di gioco.
rows: Intero che rappresenta il numero di righe di game.
cols: Intero che rappresenta il numero di colonne di game.
mines: Intero che rappresenta le mine che verranno inserite in game.
row: Intero che rappresenta una riga generata a caso.
col: Intero che rappresenta una colonna generata a caso.
index: Intero che dice a runtime quante mine sono gia state create in game.
newrow: Oggetto di classe Random che genererà una riga.
newcol: Oggetto di classe Random che genererà una colonna.
component: Oggetto che crea all'occorrenza l'icona mina o numero.
[CUT]
Potresti postare il codice che richiama il costruttore, e in particolare il codice che inizializza la matrice di JButton??
Comunque le icone settate sui pulsanti non sono certo il modo migliore di gestire l'applicazione. Un po' di sano MVC non fa mai male.. :asd:
Simone89RN
15-07-2009, 12:11
Potresti postare il codice che richiama il costruttore, e in particolare il codice che inizializza la matrice di JButton??
Comunque le icone settate sui pulsanti non sono certo il modo migliore di gestire l'applicazione. Un po' di sano MVC non fa mai male.. :asd:
Allora ti posto 2 classi, la 1° è quella che usa il costruttore, la 2° invece possiede i metodi che danno righe e colonne della matrice:
package campoMinato;
import javax.swing.*;
import java.awt.*;
public class MyGamePanel extends JPanel {
private JButton [][] game;
MyGameSystem system;
public MyGamePanel(MyNewGameDialogBox attributes) {
super(new GridLayout(attributes.getAltezza(), attributes.getLarghezza()));
game = new JButton [attributes.getAltezza()][attributes.getLarghezza()];
for (int i = 0; i < attributes.getAltezza(); i++) {
for (int j = 0; j < attributes.getLarghezza(); j++) {
game[i][j] = new JButton();
add(game[i][j]);
}
}
system = new MyGameSystem(game,attributes.getAltezza(),attributes.getLarghezza(),attributes.getMines());
system.CreateGame();
}
}
package campoMinato;
import javax.swing.*;
import java.awt.*;
import ascoltatori.*;
public class MyNewGameDialogBox extends JDialog {
private Box labels, textfields, buttons;
private JButton ok, annulla;
private JTextField width, height, mines;
private MyFrame mainFrame;
public MyNewGameDialogBox(MyFrame parent) {
super(parent,"Nuova Partita");
mainFrame = parent;
setLayout(new FlowLayout());
setSize(200,200);
labels = Box.createVerticalBox();
textfields = Box.createVerticalBox();
buttons = Box.createVerticalBox();
height = new JTextField(3);
width = new JTextField(3);
mines = new JTextField(3);
ok = new JButton("OK");
annulla = new JButton("Annulla");
labels.add(new JLabel("Altezza:"));
labels.add(Box.createVerticalStrut(20));
labels.add(new JLabel("Larghezza:"));
labels.add(Box.createVerticalStrut(20));
labels.add(new JLabel("Mine:"));
textfields.add(height);
textfields.add(Box.createVerticalStrut(20));
textfields.add(width);
textfields.add(Box.createVerticalStrut(20));
textfields.add(mines);
buttons.add(ok);
buttons.add(Box.createVerticalStrut(40));
buttons.add(annulla);
Container c = getContentPane();
c.add(labels);
c.add(textfields);
c.add(buttons);
ok.addActionListener(new MyNewGameDialogBoxListener(mainFrame, this));
annulla.addActionListener(new MyNewGameDialogBoxListener(mainFrame, this));
}
public int getAltezza() {
int h = Integer.parseInt(height.getText());
return h;
}
public int getLarghezza() {
int h = Integer.parseInt(width.getText());
return h;
}
public int getMines() {
int h = Integer.parseInt(mines.getText());
return h;
}
}
malocchio
15-07-2009, 16:27
Prima di tutto: la variabile globale component dovrebbe essere locale: ogni metodo usa la propria variabile, è una questione di sicurezza e soprattutto ti aiuta a scrivere codice corretto.
Domanda: cosa fanno le classi MineComponent e NumberComponent????
Ora mi verrebbe da consigliarti di fare così: crea un array globale di icone nella classe MyGameSystem
Icon[] icone = new Icon[10]; //dichiarazione
//nel costruttore
icone[0] = null;
for (int i = 1; i <= 9; i++) {
icone[i] = new Icon("Icone/j"+ i +".gif");
}
Utilizza questi oggetti icona per costruire gli oggetti *Component e modifica il costruttore di questi in modo che accetti come parametro direttamente l'icona piuttosto che il suo percorso.
public void CreateMines(int r, int c) {
if (game[r][c].getDisabledIcon() == null) {
component = new MineComponent(icone[9])
game[r][c].setDisabledIcon(icone[9]);
} else {
index--;
}
}
public int CountMines(int r, int c) {
int n_mines = 0;
for (int i = r-1; i <= r+1; i++) {
for (int j = c-1; j <= c+1; j++) {
if (((i >= 0) && (j >= 0)) && ((i < rows) && (j < cols))) {
if (game[i][j].getDisabledIcon() == icone[9]) //c'è una mina!
n_mines++;
}
}
}
return n_mines;
}
Quindi icone[9] vuol dire mina, icone[1-8] vuol dire numero, icone[0] è semplicemente null
Non è di certo il massimo, ma almeno vedi se così funziona
Simone89RN
15-07-2009, 18:41
Prima di tutto: la variabile globale component dovrebbe essere locale: ogni metodo usa la propria variabile, è una questione di sicurezza e soprattutto ti aiuta a scrivere codice corretto.
Domanda: cosa fanno le classi MineComponent e NumberComponent????
Ora mi verrebbe da consigliarti di fare così: crea un array globale di icone nella classe MyGameSystem
Icon[] icone = new Icon[10]; //dichiarazione
//nel costruttore
icone[0] = null;
for (int i = 1; i <= 9; i++) {
icone[i] = new Icon("Icone/j"+ i +".gif");
}
Utilizza questi oggetti icona per costruire gli oggetti *Component e modifica il costruttore di questi in modo che accetti come parametro direttamente l'icona piuttosto che il suo percorso.
public void CreateMines(int r, int c) {
if (game[r][c].getDisabledIcon() == null) {
component = new MineComponent(icone[9])
game[r][c].setDisabledIcon(icone[9]);
} else {
index--;
}
}
public int CountMines(int r, int c) {
int n_mines = 0;
for (int i = r-1; i <= r+1; i++) {
for (int j = c-1; j <= c+1; j++) {
if (((i >= 0) && (j >= 0)) && ((i < rows) && (j < cols))) {
if (game[i][j].getDisabledIcon() == icone[9]) //c'è una mina!
n_mines++;
}
}
}
return n_mines;
}
Quindi icone[9] vuol dire mina, icone[1-8] vuol dire numero, icone[0] è semplicemente null
Non è di certo il massimo, ma almeno vedi se così funziona
Ti ringrazio per l'aiuto, in effetti è brutta come soluzione, ma ne ho trovata un altra da solo che credo sia meglio di questa, ho creato una matrice di booleani di dimensioni uguali a quelle della griglia di gioco e li ho settati tutti false, poi man mano che aggiungo le mine li metto a true e poi in CountMines() controllo se c'è la mina o no attraverso questa nuova matrice di booleani.:D :D
Visto che ho postato il codice ne approfitto per fare qualche domanda legata all'information hiding, oltre all'oggetto component da mettere locale, secondo te è anche meglio mettere tutti i metodi della classe MyGameSystem private anzichè public al di fuori del costruttore e del metodo CreateGame()?
Inoltre le variabili intere row e col e gli oggetti Random newrow e newcol li uso solo nel metodo CreateGame(), è meglio metterle anche quelle locali?
malocchio
15-07-2009, 19:04
Ti ringrazio per l'aiuto, in effetti è brutta come soluzione, ma ne ho trovata un altra da solo che credo sia meglio di questa, ho creato una matrice di booleani di dimensioni uguali a quelle della griglia di gioco e li ho settati tutti false, poi man mano che aggiungo le mine li metto a true e poi in CountMines() controllo se c'è la mina o no attraverso questa nuova matrice di booleani.:D :D
Visto che ho postato il codice ne approfitto per fare qualche domanda legata all'information hiding, oltre all'oggetto component da mettere locale, secondo te è anche meglio mettere tutti i metodi della classe MyGameSystem private anzichè public al di fuori del costruttore e del metodo CreateGame()?
Inoltre le variabili intere row e col e gli oggetti Random newrow e newcol li uso solo nel metodo CreateGame(), è meglio metterle anche quelle locali?
Hai fatto bene, in effetti almeno una matrice di booleani in questo caso ci vuole.
Il discorso visibilità dei membri classe è abbastanza semplice: prova a pensare ad un programma maligno che avendo accesso alle tue classi modifichi tutte i campi che può, richiami tutti i metodi a cui può accedere, in una maniera il più possibile rovinosa per il tuo programma. Ora prendi tutti i metodi e mettili private, poi seleziona i metodi che necessariamente devono essere richiamati dall'esterno della tua classe e mettili public o package(default). Ovviamente la questione è molto molto molto più complessa, e non ho neanche considerato il modificatore protected.
Possiamo in genere dire che i campi (variabili globali) di una classe sono di solito tutti private (si accedono eventualmente tramite set/get), a meno che non si tratti di costanti dichiarate final (e static) oppure di variabili che molto probabilmente devono essere utilizzate dalle sottoclassi, avendo progettato la tua classe specificatamente per essere estesa.
In generale la tua applicazione avrebbe bisogno di una riveduta globale, in quanto la progettazione delle classi non è il massimo. Sto parlando dei vari ruoli e informazioni che sono "distribuiti" nelle varie classi.
Sarebbe interessante vedere il codice delle classi *Component e dei gestori degli eventi tipo click mouse eccetera...
Adesso devo scappare, a presto:)
Simone89RN
15-07-2009, 19:18
Hai fatto bene, in effetti almeno una matrice di booleani in questo caso ci vuole.
Il discorso visibilità dei membri classe è abbastanza semplice: prova a pensare ad un programma maligno che avendo accesso alle tue classi modifichi tutte i campi che può, richiami tutti i metodi a cui può accedere, in una maniera il più possibile rovinosa per il tuo programma. Ora prendi tutti i metodi e mettili private, poi seleziona i metodi che necessariamente devono essere richiamati dall'esterno della tua classe e mettili public o package(default). Ovviamente la questione è molto molto molto più complessa, e non ho neanche considerato il modificatore protected.
Possiamo in genere dire che i campi (variabili globali) di una classe sono di solito tutti private (si accedono eventualmente tramite set/get), a meno che non si tratti di costanti dichiarate final (e static) oppure di variabili che molto probabilmente devono essere utilizzate dalle sottoclassi, avendo progettato la tua classe specificatamente per essere estesa.
In generale la tua applicazione avrebbe bisogno di una riveduta globale, in quanto la progettazione delle classi non è il massimo. Sto parlando dei vari ruoli e informazioni che sono "distribuiti" nelle varie classi.
Sarebbe interessante vedere il codice delle classi *Component e dei gestori degli eventi tipo click mouse eccetera...
Adesso devo scappare, a presto:)
Grazie per le spiegazioni. Questo topic può essere chiuso, visto che abbiamo parlato di tutt'altro argomento invece di quello che era stato preannunciato dal titolo. :) :)
malocchio
16-07-2009, 09:20
Grazie per le spiegazioni. Questo topic può essere chiuso, visto che abbiamo parlato di tutt'altro argomento invece di quello che era stato preannunciato dal titolo. :) :)
Guarda hai ragione stiamo uscendo dal topic vero e proprio, il problema è risolto, ma in questa sezione (particolarmente) succede di continuo, se non sempre!
Simone89RN
16-07-2009, 17:40
Purtroppo sono sorti altri problemi. Provo a postarli qui anche se come ho gia detto non hanno a che fare nulla col titolo del topic.
Il sistema di gioco è praticamente finito, manca solo da visualizzare le icone di mine e numeri quando i bottoni sono premuti e disabilitarli, per questo ho settato l'icona del pulsante disabilitato con setDisabledIcon(), ma quando aggiungo il listener ai bottoni, e quindi nel actionPerformed() vado a disabilitare il bottone stesso facendo button.setEnabled(false) il risultato è che il bottone viene disabilitato senza che si visualizzi l'icona.
Inoltre devo gestire anche l'icona della bandierina che appare quando l'utente clicca sul tasto destro del mouse sul bottone supponendo che in quella casella ci sia una mina. So che devo usare una classe che implementi l'interfaccia MouseListener, ma non so come riconoscere se il click sia stato fatto dal pulsante sinistro e destro del mouse. Chi mi sa aiutare?
Per il pulsante sinistro/destro, dato il MouseEvent me:
if(SwingUtilities.isLeftMouseButton(me)) {
...sinistro
} else if(SwingUtilities.isRightMouseButton(me)) {
...destro
}
Controlla il percorso dell'icona che usi per il pulsante disabilitato. Se usi ImageIcon e il percorso non è corretto anzichè rilasciare un'eccezione ottieni un'icona vuota - e quindi non appare nulla.
Simone89RN
17-07-2009, 09:55
Per il pulsante sinistro/destro, dato il MouseEvent me:
if(SwingUtilities.isLeftMouseButton(me)) {
...sinistro
} else if(SwingUtilities.isRightMouseButton(me)) {
...destro
}
Controlla il percorso dell'icona che usi per il pulsante disabilitato. Se usi ImageIcon e il percorso non è corretto anzichè rilasciare un'eccezione ottieni un'icona vuota - e quindi non appare nulla.
Ciao, ti confermo che il percorso è stato messo correttamente, perchè ho provato a cambiare setDisabledIcon() con semplicemente setIcon() lasciando tutto invariato, e facendo cosi le icone di default si vedono tutte bene, il problema viene fuori quando uso setDisabledIcon() che non fa vedere le icone quando si disattiva il bottone, hai qualche altra soluzione in proposito?
malocchio
17-07-2009, 10:22
Ciao, ti confermo che il percorso è stato messo correttamente, perchè ho provato a cambiare setDisabledIcon() con semplicemente setIcon() lasciando tutto invariato, e facendo cosi le icone di default si vedono tutte bene, il problema viene fuori quando uso setDisabledIcon() che non fa vedere le icone quando si disattiva il bottone, hai qualche altra soluzione in proposito?
Non ho mai usato questi metodi, ma hai provato a richiamare setDisabledSelectedIcon() (http://java.sun.com/javase/6/docs/api/javax/swing/AbstractButton.html#setDisabledSelectedIcon(javax.swing.Icon))
E' l'unica cosa che mi potrebbe venire in mente...
Simone89RN
17-07-2009, 10:31
Non ho mai usato questi metodi, ma hai provato a richiamare setDisabledSelectedIcon() (http://java.sun.com/javase/6/docs/api/javax/swing/AbstractButton.html#setDisabledSelectedIcon(javax.swing.Icon))
E' l'unica cosa che mi potrebbe venire in mente...
Si l'avevo visto e ho provato anche questa soluzione, ma niente da fare il problema persiste quando il bottone si disattiva.
malocchio
17-07-2009, 10:43
Si l'avevo visto e ho provato anche questa soluzione, ma niente da fare il problema persiste quando il bottone si disattiva.
setIcon() (http://java.sun.com/javase/6/docs/api/javax/swing/AbstractButton.html#setIcon(javax.swing.Icon)) agisce solo sul pulsante attivato oppure rimane a pulsante disattivato?
Cioè quando lo disattivi l'icona sparisce?
Se non sbaglio l'icona settata con setIcon() (http://java.sun.com/javase/6/docs/api/javax/swing/AbstractButton.html#setIcon(javax.swing.Icon)) rimane anche nello stato disabled, se non ne viene specificata un'altra. Hai provato a sostituire a setDisabledIcon() setIcon, richiamandolo però ovviamente solo nel momento in cui fai setEnabled(false) ?
Simone89RN
17-07-2009, 12:19
setIcon() (http://java.sun.com/javase/6/docs/api/javax/swing/AbstractButton.html#setIcon(javax.swing.Icon)) agisce solo sul pulsante attivato oppure rimane a pulsante disattivato?
Cioè quando lo disattivi l'icona sparisce?
Se non sbaglio l'icona settata con setIcon() (http://java.sun.com/javase/6/docs/api/javax/swing/AbstractButton.html#setIcon(javax.swing.Icon)) rimane anche nello stato disabled, se non ne viene specificata un'altra. Hai provato a sostituire a setSelectedIcon setIcon, richiamandolo però ovviamente solo nel momento in cui fai setEnabled(false) ?
Allora per la prima domanda, l'icona è visibile come dici tu sia nello stato attivo (si vede bene) che nello stato disattivo (si vede trasparente).
La seconda invece non mi è tanto chiara, perchè hai citato un metodo che non ho mai usato finora che è setSelectedIcon(), potresti rispiegarla meglio?
malocchio
17-07-2009, 13:10
Allora per la prima domanda, l'icona è visibile come dici tu sia nello stato attivo (si vede bene) che nello stato disattivo (si vede trasparente).
La seconda invece non mi è tanto chiara, perchè hai citato un metodo che non ho mai usato finora che è setSelectedIcon(), potresti rispiegarla meglio?
Ah scusami, volevo dire setDisabledIcon(), il metodo che hai usato tu!
Edito subito...
Simone89RN
19-07-2009, 23:45
Ok problema risolto, ora però mi manca da gestire la bandierina che l'utente con il tasto destro del mouse mette perchè crede che in quella casella ci sia la mina.
Mi servirebbe un metodo che all'evento del click del pulsante destro del mouse disattivi il bottone solo per il click del tasto sinistro del mouse ma non per quello destro, il setEnabled credo lo disattivi per qualunque evento giusto?
Esiste un metodo che faccia quello che mi serve oppure mi tocca gestire gli eventi dei pulsanti?
malocchio
20-07-2009, 00:51
Ok problema risolto, ora però mi manca da gestire la bandierina che l'utente con il tasto destro del mouse mette perchè crede che in quella casella ci sia la mina.
Mi servirebbe un metodo che all'evento del click del pulsante destro del mouse disattivi il bottone solo per il click del tasto sinistro del mouse ma non per quello destro, il setEnabled credo lo disattivi per qualunque evento giusto?
Esiste un metodo che faccia quello che mi serve oppure mi tocca gestire gli eventi dei pulsanti?
Non sono perfettamente documentato ma posso dirti con buona sicurezza che te lo devi gestire da te, creando una matrice di flag di stato...
Simone89RN
22-07-2009, 18:09
Ok tralasciando l'argomento "bandierine", ora alla mia applicazione manca solo da poter essere salvata e caricata su e da File System. E qui avrei bisogno di chiarimenti sulla classe JFileChooser che uso per trovare il file del gioco nel caso di caricamento e di scriverne il nome nel caso di salvataggio.
Inanzitutto visto che si tratta di salvare un vero e proprio progetto utilizzo la classe ObjectOutputStream in modo da poter serializzare tutte le classi che utilizzo a partire dal mio Frame, ma questa classe nel costruttore richiede un riferimento di tipo OutputStream e per questo uso la classe FileOutputStream per creare il file da passare a ObjectOutputStream.
Parliamo di salvataggio:
Quando vado nel blocco try per creare il mio FileOutputStream gli passo al costruttore:
try {
f = new FileOutputStream(chooser.getSelectedFile().getName());
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
con f che è riferimento di classe FileOutputStream e chooser è un JFileChooser.
Poi nel try di creazione del file ObjectOutputStream quando gli passo come parametro f, tutto va a buon fine senza eccezioni, ma quando vado a vedere se nella cartella che avevo scelto per salvare, non compare nessun file. La mia domanda è questa: il metodo chooser.getSelectedFile().getName() ti da effettivamente il percorso di salvataggio scelto con JFileChooser compreso il nome che l'utente ha scritto per creare il file?
malocchio
22-07-2009, 18:32
Ok tralasciando l'argomento "bandierine", ora alla mia applicazione manca solo da poter essere salvata e caricata su e da File System. E qui avrei bisogno di chiarimenti sulla classe JFileChooser che uso per trovare il file del gioco nel caso di caricamento e di scriverne il nome nel caso di salvataggio.
Inanzitutto visto che si tratta di salvare un vero e proprio progetto utilizzo la classe ObjectOutputStream in modo da poter serializzare tutte le classi che utilizzo a partire dal mio Frame, ma questa classe nel costruttore richiede un riferimento di tipo OutputStream e per questo uso la classe FileOutputStream per creare il file da passare a ObjectOutputStream.
Parliamo di salvataggio:
Quando vado nel blocco try per creare il mio FileOutputStream gli passo al costruttore:
try {
f = new FileOutputStream(chooser.getSelectedFile().getName());
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
con f che è riferimento di classe FileOutputStream e chooser è un JFileChooser.
Poi nel try di creazione del file ObjectOutputStream quando gli passo come parametro f, tutto va a buon fine senza eccezioni, ma quando vado a vedere se nella cartella che avevo scelto per salvare, non compare nessun file. La mia domanda è questa: il metodo chooser.getSelectedFile().getName() ti da effettivamente il percorso di salvataggio scelto con JFileChooser compreso il nome che l'utente ha scritto per creare il file?
http://java.sun.com/javase/6/docs/api/java/io/ObjectOutputStream.html#ObjectOutputStream(java.io.OutputStream)
e
http://java.sun.com/javase/6/docs/api/java/io/ObjectOutputStream.html#writeObject(java.lang.Object)
e, ovviamente
http://java.sun.com/javase/6/docs/api/java/io/ObjectOutputStream.html#close()
Simone89RN
22-07-2009, 18:53
http://java.sun.com/javase/6/docs/api/java/io/ObjectOutputStream.html#ObjectOutputStream(java.io.OutputStream)
e
http://java.sun.com/javase/6/docs/api/java/io/ObjectOutputStream.html#writeObject(java.lang.Object)
e, ovviamente
http://java.sun.com/javase/6/docs/api/java/io/ObjectOutputStream.html#close()
Mi sa che non hai capito il mio problema, tutti questi link che hai postato riguardano quello che dovrei fare dopo il catch che ho postato, mentre invece il mio problema è un chiarimento sulla classe JFileChooser, io utilizzo i metodi getSelectedFile().getName() perchè penso che danno il percorso di salvataggio che viene scelto sulla finestra del JFileChooser compreso anche il nome del file che poi verrà creato, da passare al costruttore di FileOutputStream in modo che venga creato il file in quel percorso, ma evidentemente non è come credo visto che non compare nessun file nel percorso scelto con JFileChooser.
malocchio
22-07-2009, 19:11
Mi sa che non hai capito il mio problema, tutti questi link che hai postato riguardano quello che dovrei fare dopo il catch che ho postato, mentre invece il mio problema è un chiarimento sulla classe JFileChooser, io utilizzo i metodi getSelectedFile().getName() perchè penso che danno il percorso di salvataggio che viene scelto sulla finestra del JFileChooser compreso anche il nome del file che poi verrà creato, da passare al costruttore di FileOutputStream in modo che venga creato il file in quel percorso, ma evidentemente non è come credo visto che non compare nessun file nel percorso scelto con JFileChooser.
Ah allora scusa.
Hai provato a fare un System.out.print di getSelectedFile().getName() ?
Simone89RN
22-07-2009, 21:26
Ah allora scusa.
Hai provato a fare un System.out.print di getSelectedFile().getName() ?
Grazie, attraverso la console ho scoperto che al posto di getName() dovevo usare getPath(). Allora il salvataggio è corretto.
Per quanto riguarda il caricamento invece quando vado a cercare il mio file sempre con JFileChooser, lo trovo e lo carico, ma l'applicazione non ascolta più gli eventi dei bottoni e nemmeno di un nuovo salvataggio o caricamento. Io utilizzo questo codice:
package ascoltatori;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.filechooser.*;
import campoMinato.MyFrame;
public class MyLoadGameListener implements ActionListener {
JFileChooser chooser;
FileNameExtensionFilter filter;
MyFrame mainFrame, newFrame;
public MyLoadGameListener(MyFrame parent) {
mainFrame = parent;
chooser = new JFileChooser();
filter = new FileNameExtensionFilter("CMP Files", "cmp");
chooser.setFileFilter(filter);
}
public void actionPerformed(ActionEvent e) {
JMenuItem loadGame = (JMenuItem) e.getSource();
int returnVal = chooser.showOpenDialog(loadGame);
if (returnVal == JFileChooser.APPROVE_OPTION) {
FileInputStream f = null;
ObjectInputStream is = null;
try {
f = new FileInputStream(chooser.getSelectedFile().getPath());
is = new ObjectInputStream(f);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}
try {
newFrame = (MyFrame) is.readObject();
newFrame.setVisible(true);
mainFrame.setVisible(false);
is.close();
} catch (IOException e1) {
e1.printStackTrace();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
}
}
}
Uso anche setVisible, ma non funziona. Come faccio a dare il controllo all'applicazione caricata da file?
malocchio
23-07-2009, 10:00
Grazie, attraverso la console ho scoperto che al posto di getName() dovevo usare getPath(). Allora il salvataggio è corretto.
Per quanto riguarda il caricamento invece quando vado a cercare il mio file sempre con JFileChooser, lo trovo e lo carico, ma l'applicazione non ascolta più gli eventi dei bottoni e nemmeno di un nuovo salvataggio o caricamento.
In questo caso non saprei molto come aiutarti...
Posso solo dirti che JFileChooser dovrebbe essere un JDialog per cui, una volta chiuso, dovrebbe ridare il focus al frame. Prova a fare un debug.... boh
(non ho mai usato JFileChooser):fagiano:
Simone89RN
23-07-2009, 10:48
In questo caso non saprei molto come aiutarti...
Posso solo dirti che JFileChooser dovrebbe essere un JDialog per cui, una volta chiuso, dovrebbe ridare il focus al frame. Prova a fare un debug.... boh
(non ho mai usato JFileChooser):fagiano:
Ah tranquillo finchè non scopro che le cose non funzionano come penso che dovrebbero andare, io lavoro sempre in debug, ma qui si tratta proprio che l'applicazione caricata non risponde agli eventi che ho predefinito per i JMenuItem di salvataggio e caricamento e a quelli dei bottoni della griglia di gioco, per cui debuggare serve a poco se proprio non risponde l'applicazione.
Provo a esternare questo problema sul forum con un nuovo topic visto che qui ormai siamo completamente fuori dal titolo.
malocchio
23-07-2009, 11:44
Ah tranquillo finchè non scopro che le cose non funzionano come penso che dovrebbero andare, io lavoro sempre in debug, ma qui si tratta proprio che l'applicazione caricata non risponde agli eventi che ho predefinito per i JMenuItem di salvataggio e caricamento e a quelli dei bottoni della griglia di gioco, per cui debuggare serve a poco se proprio non risponde l'applicazione.
Provo a esternare questo problema sul forum con un nuovo topic visto che qui ormai siamo completamente fuori dal titolo.
Sì, fai bene. Io purtroppo in questo caso non so aiutarti :rolleyes:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.