KuroKami69 ha scritto:
Se ho capito bene, te mi stai suggerendo di eliminare il changerownumber dal tablemodel e di metterlo nel frame. quindi nel tablemodel mettere quei 3 metodi che hai suggerito in modo che il mio tablemodel rimanga pulito
Esatto.
KuroKami69 ha scritto:
Poi, come mi avevi già consigliato, mi consigli di fare 3 metodi boolean che mi guardano che cosa è settato nei radio giusto? anche questi metodi li dovrò fare nel frame giusto? (questa parte non l'avevo capita, per questo non l'ho adottata).
No, non servono tre metodi, JRadioButton ha già il metodo
isSelected (), non ti serve altro. Chiaramente, hai bisogno di controllare il valore di ognuno dei tre radiobutton. Se vuoi puoi farti un metodo nella tua classe che restituisca una stringa (non benissimo), o usare delle costanti (molto meglio), o usare una (meglio ancora). Ad esempio, usando le enum:
public enum DisplayMode
{
CARS_AND_MOTORCYCLES,
CARS_ONLY,
MOTORCYCLES_ONLY
}
// Nella classe dell'interfaccia ...
public DisplayMode checkDisplayMode () {
if (automobileRadioButton.isSelected ()) return DisplayMode.CARS_ONLY;
else if (motoRadioButton.isSelected ()) return DisplayMode.MOTORCYCLES_ONLY;
else return DisplayMode.CARS_AND_MOTORCYCLES;
}
Ovviamente usa i radiobutton che hai scritto tu, non ricordo il nome. Questo è un buon modo per prendere un singolo valore dal gruppo di pulsanti, non l'unico, potresti accedere al ButtonGroup e recuperare il modello del bottone selezionato, ma è più rischioso e sei comunque costretto a fare un giro in più.
L'enum può essere definita anche in un file a parte, in alcuni casi può aver senso che sia all'interno di una classe, qui un po' meno.
Metto un po' di carne al fuoco, ma se non ti fidi puoi anche non farlo subito, lo studierai sul tuo libro. Qual'è il vantaggio di usare una enum? Il maggiore è che una stringa potrebbe contenere qualsiasi cosa, una enum invece gestisce proprio un set di valori.
Questo ti evita anche errori in prospettiva futura: se sbagli a scrivere una stringa, nessuno ti avverte, con una costante definita in una classe (es.
BorderLayout.NORTH) o con una enum, ricevi un errore in compilazione se inserisci un valore che non esiste.
Tra costante ed enum, però, mentre la costante è di un tipo specifico (ad es. int), l'enum non si appoggia a un altro valore (almeno per quanto interessa a te, come la gestisce il compilatore è un'altra cosa). Quindi mentre è lecito passare un valore non previsto ad int, l'unico rischio con la enum è ricevere null, che è un valore lecito (il piccolo vantaggio di usare due boolean sarebbe proprio questo, avrai sempre dei valori "corretti" e non serve nessun controllo in nessun caso, oltre a non dover definire una struttura in più o delle costanti).
Quindi potresti anche avere un metodo nel tableModel, es.
public void setDisplayMode (DisplayMode mode) che va proprio a impostare la modalità di visualizzazione del modello, che la userà anche nei suoi metodi come
getRowCount () quando vorrai filtrare le righe.
Per concludere, nel metodo in cui aggiungi i veicoli vai a richiamare quel metodo, ti salvi il valore di ritorno e in base a quello scegli cosa aggiungere, oppure (meglio, perché potresti usarlo anche dopo) chiedi al modello qual'è la modalità di visualizzazione corrente (se aggiungi il setDisplayMode è perché terrai un campo es.
currentDisplayMode nel modello, quindi aggiungerai anche un get), ricordandoti di cambiare nel modello la variabile con il set quando cambia la selezione del radio button.
KuroKami69 ha scritto:
continuo a non capire il discorso del passaggio di parametri ai costruttori. mi basta semplicemente metterli void, fare l'assegnazione e togliere il return giusto?
Questo è quello che devi fare nei set, non nei costruttori. I set dovrebbero essere dichiarati come void, fanno l'assegnazione e non ritornano nulla. I costruttori ricevono dei valori, e fanno l'assegnazione diretta o richiamano il set, ma per passare i parametri al costruttore non serve usare i set, è chi li riceve che può usarli.
Riprendendo un codice di esempio simile a quelli di prima, faccio prima a riscriverlo che a trovarlo qui dentro
public abstract class Veicolo
{
// dichiari i campi comuni ...
public Veicolo (String modello, String marca) {
this.modello = modello;
this.marca = marca;
}
public void setModello (String modello) {
this.modello = modello;
}
// set corrispondente per marca, piu' i vari get.
}
public class Automobile
{
private int capienzaBagagliaio;
public Automobile (String modello, String marca, int capienzaBagagliaio) {
super (modello, marca);
this.capienzaBagagliaio = capienzaBagagliaio;
}
public void setCapienzaBagagliaio (int capienzaBagagliaio) {
this.capienzaBagagliaio = capienzaBagagliaio;
}
}
Se tu avessi un costruttore che non prende alcun parametro in Veicolo, potresti anche scrivere il costruttore di Automobile in questo modo:
public Automobile (String modello, String marca, int capienzaBagagliaio) {
setModello (modello);
setMarca (marca);
setCapienzaBagagliaio (capienzaBagagliaio);
}
Ora come ora questa scrittura sarebbe equivalente all'altro costruttore. Automobile eredita i set da Veicolo, quindi può usarli, per il resto cambia solo che in un modo fai l'assegnazione diretta nel costruttore, nell'altro usi i set.
Cambierebbe se nel set tu facessi altro oltre all'assegnazione, ad esempio (scenario tipico) se controllassi prima il valore e lanciassi un errore nel caso in cui non sia corretto, ad esempio se viene passato un intero negativo nel setCapienzaBagagliaio.
In quel caso meglio usare sempre i set, in modo da essere sicuri che il controllo sia sempre fatto nello stesso modo. Se la classe non ha metodi set e campi final, i controlli ovviamente vanno fatti nel costruttore, qualora servano.
Ma l'importante è che tu capisca che i set non li fai nella chiamata al costruttore, quella va fatta con valori precisi, da dove vengono fuori non è importante:
new Automobile ("Alfa", "Romeo", 10); -> SI'
new Automobile (setModello ("Alfa"), ..) -> NO !!!!!!!!!!!!!!
Per l'indice vedi sotto.
KuroKami69 ha scritto:
Allora, mettiamo in ordine le cose che non capisco:
1) ho pressappoco capito quello che hai detto, ma continuo a NON capire in che modo scegliere casualmente la marca e il modello, perché io dovrò avere comunque un random da 0 a n, e se un giorno (mai) volessi aggiungere o rimuovere modelli/marche, n dovrà cambiare e lo dovrò fare io manualmente. amenochè te non mi stia dicendo di prendere quel numeretto la dal numero di righe dei miei .txt. in questo modo sarà sempre automatica la cosa
Per la marca, ad esempio, dovrai avere un indice casuale nel range che va da 0 al numero di marche totali. Chi ha il numero delle marche totali? La lista, ovviamente. Stai salvando tutte le marche in un List <String> (altrimenti da dove lo prendi l'elemento casuale) quindi ti basta prendere un
random.nextInt (0, listaMarche.size ()). Te l'ho anche scritto nella mia classe CostruttoreVeicoli ...
La cosa buona di fare così è che se un giorno aggiungi marche, cambierai il file, ma se la lista legge dal file non hai alcun problema, non devi toccare il codice della classe. Il numero di righe del file non è una soluzione sicura, potresti avere più veicoli per riga in futuro, o saltare una riga per sbaglio quando scrivi il file, o trovare un valore per te scorretto e saltare la riga in fase di lettura ...
Tra l'altro la lista oggi la prendi dal file, domani magari la popoli leggendo una tabella di veicoli su una pagina web, prendendo dati da un database esterno, a partire da una request http che ti restituisce un json, o altro. Ma questo per il resto del codice non fa alcuna differenza!
KuroKami69 ha scritto:
2) nel tablemodel metto solo add e remove, che poi chiamerò nel frame nel metodo changerownumber. fin qua ho capito. magari dopo aver letto bene il codice mi sarà più chiaro ma la logica l'ho capita. non mi è chiarissimo il discorso di istAutoSelected che ritorna true o false. tempo fa mi diceste che i metodi is esistono già e che non devo farli io (se ricordo bene) ma qua mi sembra di capire che lo devo fare io giusto? nel frame. anche se sarà una roba tipo boolean isAutoSelected(){return true;}
Detto sopra, isSelected () è il metodo di JRadioButton che va usato, se vuoi usare un metodo che lo utilizzi internamente per non dover scriverlo più volte per ogni valore possibile, meglio ancora.
KuroKami69 ha scritto:
3) come fare dentro al getValueAt. più che immaginarmi un if, non riesco a pensare ad altro. forse, e dico forse, come suggerivate voi, fare un casting ad auto/moto, ma questa parte non l'ho ben capita. quindi son sempre in alto mare.
4) come visualizzare solo le colonne che mi interessano. all'inizio pensavo semplicemente di dire, nel getColumnName, se è moto, allora questa me la cambi in questo, e le altre le togli, se entrambi, allora mi mostri solo queste. ma dovrei anche modificare i valori di getColumnCount altrimenti non serve a niente. questo è quello che ho pensato io, che chiaramente è sbagliato. non ho capito come sfruttare quei suggerimenti sul nascondere le colonne che mi dicevate.
Questo come già detto dipende da quali colonne vuoi visualizzare, e se vuoi mostrare i tipi di veicoli assieme o meno.
E' sempre la stessa storia: se vuoi vedere tutto assieme, ti conviene avere delle colonne fisse e non cambiare niente. Del resto come faresti quando devi mostrare entrambe? Non puoi cambiare l'header in base ad ogni riga, non ti pare?
Al massimo potresti usare "attributo1", "attributo2" o cose del genere nell'header, e cambiare i valori in base al tipo di veicolo, ma mi pare molto brutto, no?
Come in precedenza, ti consiglio di usare tutte le colonne nella tabella, e di lasciare vuote le celle dell'altro tipo di veicolo. Immagina di avere solo questi valori:
Marca Modello CapienzaBagagliaio AltezzaSella
Fiat Punto 40 /
BMW 1200 / 0.82
Ovviamente ho messo valori a caso. Una tabella del genere ci può stare, hai tutti i valori, solo che alcuni saranno vuoti.
Nel getValueAt gestire la cosa è facilissimo (ancora di più negli altri metodi):
Per gli indici "comuni" di columnIndex, basta prendere il veicolo e restituire il risultato di getMarca (), getModello (), etc.
Per gli indici corrispondenti a colonne per sole auto, controlli con instanceof che tipo di veicolo hai in mano. Se hai Auto allora fai un cast e prendi il metodo specifico dell'Automobile (es. getCapienzaBagagliaio ()), se hai una Moto, ritorni "/", "ND", "", o quello che vuoi.
Viceversa per le colonne relative alle moto.
Quando la modalità di visualizzazione sarà solo moto o solo auto, potresti anche pensare di nascondere le colonne vuote, ma onestamente penso che questo sia troppo difficile per te al momento, dovresti sincronizzare tutti i vari metodi, e farlo "bene".
E come si diceva, se sei disposto a non vedere più i veicoli assieme puoi anche pensare di fare due modelli diversi, in quel caso le colonne non darebbero alcun problema, usi solo quelle "corrette", ma secondo me perderesti molto.