Jframe jtable

di il
230 risposte

230 Risposte - Pagina 13

  • Re: Jframe jtable

    KuroKami69 ha scritto:


    visto che quasi tutti i miei get sono sulla superclasse veicolo, non posso semplicemente cambiare automobile in veicolo, per gli attributi comuni, e poi metterci un if sugli attributi specifici? per esempio, se invece di essere selezionato auto, c'è moto, nPosti mi diventa parabrezza, e sarà un moto.getParabrezza()
    Ne abbiamo parlato più volte. Puoi usare una lista di Veicoli e quel veicoli.get (rowIndex) lo assegni ad un oggetto Veicolo. Fai il cast ad Automobile o Moto solo se serve.
  • Re: Jframe jtable

    Te consigli quindi, nell'add, di mettere veicolo.add(new Veicolo(parametri)) giusto?
    e dopo nel case faccio un casting ad auto/moto
    però ora ti pongo una domanda
    gli array con le marche, e di conseguenza i modelli, han grandezza differente, auto ne ha 80, moto 53. quando creo veicolo io devo dargli un valore, quindi come faccio a gestire questa cosa?
  • Re: Jframe jtable

    Perché mi dice
    Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: Veicolo cannot be cast to Automobile
             at AutomobileTableModel.getValueAt(AutomobileTableModel.java:94)
    
    cioè ok mi dice "hey veicolo non può essere convertito in automobile" nonostante il downcasting sia possibile, quindi perché me lo dà? mmh
  • Re: Jframe jtable

    KuroKami69 ha scritto:


    Te consigli quindi, nell'add, di mettere veicolo.add(new Veicolo(parametri)) giusto?
    e dopo nel case faccio un casting ad auto/moto
    No, non aggiungi un Veicolo. La lista è parametrizzata per contenere oggetto Veicolo, ma tu andrai a inserire oggetti concreti, Automobile o Moto (Veicolo ha senso che sia una classe astratta, quindi nemmeno istanziabile, non ha molto senso poter creare un Veicolo, come è fatto un veicolo generico?). Una volta che dichiari una ArrayList <Veicolo> non ha importanza quale tipo di oggetto inserisci quando lo crei, l'importante è che sia una sottoclasse di veicolo, spero che questo sia chiaro, ma penso lo avessimo già detto. Il cast ti serve quando andrai a prendere un oggetto e avrai bisogno di "vederlo" come Automobile o Moto, per prendere proprietà non definite in Veicolo. In quel caso userai prima instanceof per testare il tipo di oggetto e poi un opportuno cast.

    KuroKami69 ha scritto:


    Gli array con le marche, e di conseguenza i modelli, han grandezza differente, auto ne ha 80, moto 53. quando creo veicolo io devo dargli un valore, quindi come faccio a gestire questa cosa?
    Praticamente ho già risposto. Devi ora decidere come creare Moto e Automobile. In una applicazione normale sarebbe l'utente che attraverso dei campi sceglie il tipo di veicolo e ne setta i parametri, tu dovresti solo leggere i dati e ricostruire l'oggetto che passi alla lista.
    Se vuoi che anche questo sia casuale (sigh ... ) fatti quantomeno un metodo FUORI dalla classe con il modello o i vari componenti grafici, ma nella classe che contiene i dati con marche, modelli, etc. (esterna a quelle dunque). Ad esempio, questa potrebbe essere una soluzione su come impostare la cosa, è abbozzata ma ti dovrebbe dare lo spunto:
    
    public class CostruttoreVeicoli
    {
    	private List <String> modelliAuto;
    	private List <String> modelliMoto;
    	
    	// ... altre strutture ...
    	
    	private Random random = new Random ();
    	
    	// nel costruttore leggi da file tutte le marche etc. e "popoli" le liste.
    	// Nella classe con i componenti (meglio nascondere tutta questa logica al modello) tieni un oggetto CostruttoreVeicoli, e quando necessario chiamerai costruttoreVeicoli.creaVeicoloCasuale ();
    	
    	public Veicolo creaVeicoloCasuale () {
    		
    		boolean tipoMacchina = random.nextBoolean ();	
    		
    		if (tipoMacchina) {
    		
    			String modello = modelliAuto.get (random.nextInt (modelliAuto.size ()));
    			
    			// ...
    			
    			return new Automobile (modello, ...);
    		}
    		else {
    			
    			String modello = modelliMoto.get (random.nextInt (modelliMoto.size ()));
    			
    			// ...
    			
    			return new Moto (modello, ...);
    		}
    	}
    }
    
  • Re: Jframe jtable

    Ansharja ha scritto:


    KuroKami69 ha scritto:


    Te consigli quindi, nell'add, di mettere veicolo.add(new Veicolo(parametri)) giusto?
    e dopo nel case faccio un casting ad auto/moto
    No, non aggiungi un Veicolo. La lista è parametrizzata per contenere oggetto Veicolo, ma tu andrai a inserire oggetti concreti, Automobile o Moto (Veicolo ha senso che sia una classe astratta, quindi nemmeno istanziabile, non ha molto senso poter creare un Veicolo, come è fatto un veicolo generico?). Una volta che dichiari una ArrayList <Veicolo> non ha importanza quale tipo di oggetto inserisci quando lo crei, l'importante è che sia una sottoclasse di veicolo, spero che questo sia chiaro, ma penso lo avessimo già detto. Il cast ti serve quando andrai a prendere un oggetto e avrai bisogno di "vederlo" come Automobile o Moto, per prendere proprietà non definite in Veicolo. In quel caso userai prima instanceof per testare il tipo di oggetto e poi un opportuno cast.

    KuroKami69 ha scritto:


    Gli array con le marche, e di conseguenza i modelli, han grandezza differente, auto ne ha 80, moto 53. quando creo veicolo io devo dargli un valore, quindi come faccio a gestire questa cosa?
    Praticamente ho già risposto. Devi ora decidere come creare Moto e Automobile. In una applicazione normale sarebbe l'utente che attraverso dei campi sceglie il tipo di veicolo e ne setta i parametri, tu dovresti solo leggere i dati e ricostruire l'oggetto che passi alla lista.
    Se vuoi che anche questo sia casuale (sigh ... ) fatti quantomeno un metodo FUORI dalla classe con il modello o i vari componenti grafici, ma nella classe che contiene i dati con marche, modelli, etc. (esterna a quelle dunque). Ad esempio, questa potrebbe essere una soluzione su come impostare la cosa, è abbozzata ma ti dovrebbe dare lo spunto:
    
    public class CostruttoreVeicoli
    {
    	private List <String> modelliAuto;
    	private List <String> modelliMoto;
    	
    	// ... altre strutture ...
    	
    	private Random random = new Random ();
    	
    	// nel costruttore leggi da file tutte le marche etc. e "popoli" le liste.
    	// Nella classe con i componenti (meglio nascondere tutta questa logica al modello) tieni un oggetto CostruttoreVeicoli, e quando necessario chiamerai costruttoreVeicoli.creaVeicoloCasuale ();
    	
    	public Veicolo creaVeicoloCasuale () {
    		
    		boolean tipoMacchina = random.nextBoolean ();	
    		
    		if (tipoMacchina) {
    		
    			String modello = modelliAuto.get (random.nextInt (modelliAuto.size ()));
    			
    			// ...
    			
    			return new Automobile (modello, ...);
    		}
    		else {
    			
    			String modello = modelliMoto.get (random.nextInt (modelliMoto.size ()));
    			
    			// ...
    			
    			return new Moto (modello, ...);
    		}
    	}
    }
    
    io voglio che il veicolo sia scelto dall'utente con i jradiobutton
    ma perdonami, ho cercato esempi online ma non capisco come strutturare la cosa
    mi sto incasinando per quella che so essere una banalità
    secondo quanto detto da te, il metodo che ho riadattato e postato prima è corretto, a seconda di quello che sceglie l'utente mi crea o un'auto o una moto e gli assegna l'indice appropriato.
    per favore se puoi, quando mi (ri)spieghi qualcosa, mettici un esempio pratico, anche solo una riga di codice, cosìcchè possa capire meglio la cosa
  • Re: Jframe jtable

    KuroKami69 ha scritto:


    mi sto incasinando per quella che so essere una banalità
    Già .... a quando il libro e lo studio "serio"??
  • Re: Jframe jtable

    Ahaha il libro c'è, ma prima voglio finire questa cosa, così chiudo questo capitolo e ne inizio uno nuovo con il libro
    c'è da dire che poi vorrei prendermi un libro dedicato a queste cose, awt e swing mmh
  • Re: Jframe jtable

    KuroKami69 ha scritto:


    Ahaha il libro c'è, ma prima voglio finire questa cosa, così chiudo questo capitolo e ne inizio uno nuovo con il libro
    Ok

    KuroKami69 ha scritto:


    c'è da dire che poi vorrei prendermi un libro dedicato a queste cose, awt e swing mmh
    A parte che sulle interfacce grafiche desktop Java, se parliamo di AWT/Swing, non c'è tantissimo come libri (e meno ancora in italiano). Su JavaFX c'è un po' di più ma in inglese, perché è un framework moderno e in evoluzione.
    E comunque ti conviene solo DOPO che hai passato ALMENO 6~8 mesi a studiare sul linguaggio Java (e non sul framework X, libreria Y, ecc..)
  • Re: Jframe jtable

    KuroKami69 ha scritto:


    public void changeRowNumber(int rowIndex)
       {
          int size = veicoli.size();
          if (!(veicoli.size() == rowIndex))
          {
             if (veicoli.size() > rowIndex)
             {
                while(veicoli.size() > rowIndex)
                veicoli.remove(rowIndex);
                fireTableRowsDeleted(veicoli.size()-1, size-1);
             }
             else
             {
                while(veicoli.size() < rowIndex)
                {
                   int n = d.inx();
                   int a = d.rnd(80);
                   int m = d.rnd(53);
                   if(visualizza.equals ("auto")) 
                        veicoli.add (new Automobile (d.setMarcaAuto(a), [...]));
                   else if (visualizza.equals ("moto"))
                        veicoli.add (new Moto (d.setMarcaAuto(m), d.setModelloAuto(m), [...]));
                   else
                   {
                      veicoli.add (new Moto(d.setMarcaAuto(a), d.setModelloAuto(a), [...])));
                      veicoli.add (new Automobile(d.setMarcaAuto(m), d.setModelloAuto(m), [...]));
                   }
                }
                fireTableRowsInserted(size, rowIndex-1);
             }
          }
       }

    KuroKami69 ha scritto:


    [...] Secondo quanto detto da te, il metodo che ho riadattato e postato prima è corretto, a seconda di quello che sceglie l'utente mi crea o un'auto o una moto e gli assegna l'indice appropriato.
    [...]
    per favore se puoi, quando mi (ri)spieghi qualcosa, mettici un esempio pratico, anche solo una riga di codice, cosìcchè possa capire meglio la cosa
    Questo non possiamo dirlo, il codice che avevi messo e che riposto sopra, un po' sistemato perché prima non si capiva niente, è mancante e scritto male.

    - Cos'è d? Si intuisce cosa faccia, ma per il resto ...
    - Usare dei set nei costruttori non ha alcun senso. Oltre al fatto che quei metodi dovrebbero ritornare void, quindi sarebbe proprio errata l'istruzione a livello di sintassi, il costruttore serve proprio a settare i campi di un oggetto in base ai parametri che riceve, tu fai dei set su un oggetto d che dovrebbe essere il tuo "distributore", dentro al costruttore della singola auto o moto.
    A me non pare corretto ...
    - La logica dell'add è quantomeno da rivedere, se può essere giusto il modo in cui aggiungi auto o moto nel caso di visualizzazione singola (ti avevo suggerito di non usare una stringa per la modalità di visualizzazione, ma immaginavo che lo avresti fatto, ok), è sbagliato il modo in cui aggiungi un'auto e una moto nel caso di visualizzazione "mista", tu aggiungi sempre una e una, ma se dovessi aggiungere un numero dispari di righe faresti un inserimento di troppo, quindi devi quantomeno controllare quello.

    E questo, a dire il vero, è anche il meno: ti ho suggerito fin dall'inizio di NON usare quel metodo all'interno del tablemodel. Il tablemodel dovrebbe avere un metodo che aggiunge un veicolo (o una lista di veicoli) alla propria lista di veicoli, e un metodo che rimuove un veicolo, o una serie di veicoli. Punto.
    Tutto il resto, ovvero scegliere quali veicoli aggiungere, crearli in modo casuale o tutto il casino che vuoi fare, va fatto all'esterno (non dire che non l'avevo scritto più di una volta).
    E' una serie di forzature che ti costringono tra l'altro a usare quelle due istruzioni oscene:

    int a = d.rnd(80);
    int m = d.rnd(53);
    Ma chi è il tablemodel, il mago Forest? Che ne sa che esistono 80 marche di auto e 53 di moto, o quello che è, ma stiamo scherzando?
    Tutto questo va fatto all'esterno ! (e la mia classe CostruttoreVeicoli, per quanto incompleta, è un modo per farlo)

    Mi chiedi un esempio pratico, e del codice (e non è che non ne abbia messi), ma se prima non segui i suggerimenti e ti incanali per le tue strade, non puoi aspettarti che ti veniamo in soccorso.

    Farò un tentativo, ma non suggerendoti qualcosa a mio parere sbagliato (cioè continuare in quella maniera), questo no.
    Ti rifaccio vedere con uno schema molto abbozzato quello che ho detto a parole.

    Nella classe del tablemodel rimuovi prima di tutto quel public void changeRowNumber(int rowIndex). Poi aggiungi questi metodi (considero ora che la tua lista di veicoli sia definita come List <Veicolo> veicoli all'inizio della classe):
    public void addVeicolo (Veicolo veicolo) {
    	veicoli.add (veicolo);
    	// inserisci un fireTableRowsInserted con gli indici corretti
    }
    public void removeVeicolo (int rowIndex) {
    	// controlli che la rimozione sia corretta
    	if (rowIndex < 0 || rowIndex >= veicoli.size ()) return;
    	veicoli.remove (rowIndex);
    	// inserisci un fireTableRowsDeleted con gli indici corretti
    }
    
    // FACOLTATIVO:
    
    public void addVeicoli (List <Veicolo> altriVeicoli) {
    	veicoli.addAll (altriVeicoli);
    	// inserisci un fireTableRowsInserted con gli indici corretti
    }
    Questo è su per giù quello che deve sapere far il modello in termini di inserimenti (con l'ultimo metodo facoltativo, se non vuoi dover chiamare in loop addVeicolo () quando sai di dover già aggiungere un insieme di veicoli).

    Nota che add e remove potrebbero anche restituire tipi diversi da void, ad esempio un boolen che dice se l'inserimento/rimozione è andato a buon fine (nel caso della rimozione, come vedi, non è sempre così).

    Tutto il resto non è di sua competenza.

    Questa soluzione ti consente di avere codice riutilizzabile e mantenibile. Il modello è ovviamente legato al tipo di oggetti che contiene (veicolo), non può essere altrimenti (anche se qualcosa si potrebbe fare a riguardo con una superclasse più generica, ma dimenticalo), ma una volta che cambi il numero di marche, di modelli, o di qualsiasi altra cosa, la tua classe del modello non si "rompe", non sei costretto ad aggiornare quei numeri (53, 80) o chissà quali altre boiate.
    Ancora meglio, dai la possibilità di aggiungere i veicoli in più modi. La volta che decidi di salvarti il tuo database di veicoli su file, per ripristinarlo alla volta successiva, o di aggiungere i veicoli con dei campi scelti dall'utente, o qualsiasi altra cosa (quello che stai facendo adesso verosimilmente non lo farai mai più), la tua classe è già pronta, non va cambiata, continuerai a chiamare addVeicolo () e gli altri metodi, preoccupandoti dall'esterno di che oggetti devi passare e come li crei.

    Ora, immaginando che vuoi continuare a inserire veicoli in modo casuale in base al valore dello spinner, nella classe dove hai il listener che ascolta i cambiamenti del numero selezionato dallo spinner ci sposti quel metodo changeRowNumber, quindi l'invocazione sarà uguale, tranne per il fatto che non farai tableModel.changeRowNumber (valoreDelloSpinner) ma changeRowNumber (valoreDelloSpinner). Quel metodo sarà un po' diverso:
    public void changeRowNumber (int newRowCount) // non stai passando un indice di riga, quindi usa un nome più appropriato.
    {
    	int oldRowCount = <nomeDellaTuaTabella>.getRowCount ();
    	if (oldRowCount == newRowCount) return; 
    	// se non vuoi usare un return, usa if (oldRowCount != newRowCount), non if (! (... == ...))
    	
    	if (oldRowCount > newRowCount) {
    		while (<nomeDellaTuaTabella>.getRowCount () > newRowCount)
    			<nomeDelTableModel>.removeVeicolo (newRowCount);
    		// puoi farlo anche in modo diverso, ad es. calcoli n = oldRowCount - newRowCount e fai un loop da 0 a n.
    		// non serve più il fire qui !
    	}
    	else {
    		// Questa parte puoi farla in più modi.
    		// Assumendo che vuoi aggiungere veicoli in base al valore del radio button, controlli prima il radio button.
    		// Assumiamo che la stringa visualizza valga ancora "auto" o "moto" o "entrambe" in base a quel valore, io userei due booleani.
    		// Assumiamo che vuoi ancora costruire i veicoli in modo "casuale".
    		if (visualizza.equals ("auto")) {
    			while (<nomeDellaTuaTabella>.getRowCount () < newRowCount) 
    				<nomeDelTableModel>.addVeicolo (costruttoreVeicoli.creaAutomobileCasuale ());
    		}
    		else if (visualizza.equals ("moto")) {
    			while (<nomeDellaTuaTabella>.getRowCount () < newRowCount)
    				<nomeDelTableModel>.addVeicolo (costruttoreVeicoli.creaMotoCasuale ());
    		}
    		else {
    			// Come detto non puoi aggiungere un veicolo di un tipo e uno di un altro senza controlli.
    			// Qui sotto presuppongo che tu "sorteggi" ogni volta un veicolo casuale, che potra' essere auto o moto di volta in volta.
    			while (<nomeDellaTuaTabella>.getRowCount () < newRowCount)
    				<nomeDelTableModel>.addVeicolo (costruttoreVeicoli.creaVeicoloCasuale ());
    		}
    		// non serve più il fire qui !
    	}
    }
    Leggi i vari commenti. Il punto è che anche qui, se vuoi usare la casualità, non è l'interfaccia grafica che decide quali valori passare, deve essere la classe che "sa" quali modelli, marche, etc. esistono e può quindi nascondere al suo interno tutta la logica corrispondente.

    Il codice presuppone quindi che tu nell'interfaccia grafica abbia il riferimento a un oggetto costruttoreVeicoli, vedi la classe scritta in precedenza, dove solo lui sa cosa deve fare.

    Di questa classe ti basta creare un singolo oggetto, perché nel costruttore lui andrà a leggere tutti i file per salvarsi i vari valori, poi nei metodi creaMotoCasuale () etc. andrà a fare tutto quello che vuoi in base ai valori che ha.

    Ma questo ti permette di fare tutto in modo pulito, nessuno ti impedisce di cambiare la logica di inserimento, usando dei valori scelti dall'utente o altro, senza che il modello debba essere modificato ogni volta.

    Codice ne hai, consigli ne hai ricevuti moltissimi nella discussione, ora sta a te sfruttarli. Se hai dubbi chiedi, non devi per forza fare in questo modo, ma sicuramente non come stavi facendo tu prima.
  • Re: Jframe jtable

    Anzitutto grazie per la megarisposta
    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. poi, come miavevi 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).
    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? ma ancora continuo a non capire come dovrei passargli l'indice per marca e modello.
    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

    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;}

    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

    bene con questo riassunto di quello che non capisco direi che uno step per volta ce la posso fare.
    devo rileggere 2-3 volte il tuo messaggio per capirlo bene ma intanto ti ringrazio. proverò e riproverò
  • Re: Jframe jtable

    andbin ha scritto:


    KuroKami69 ha scritto:


    Ahaha il libro c'è, ma prima voglio finire questa cosa, così chiudo questo capitolo e ne inizio uno nuovo con il libro
    Ok

    KuroKami69 ha scritto:


    c'è da dire che poi vorrei prendermi un libro dedicato a queste cose, awt e swing mmh
    A parte che sulle interfacce grafiche desktop Java, se parliamo di AWT/Swing, non c'è tantissimo come libri (e meno ancora in italiano). Su JavaFX c'è un po' di più ma in inglese, perché è un framework moderno e in evoluzione.
    E comunque ti conviene solo DOPO che hai passato ALMENO 6~8 mesi a studiare sul linguaggio Java (e non sul framework X, libreria Y, ecc..)
    certamente in futuro. anche se pensavo di iniziare anche altro una volta imparato bene java
  • Re: Jframe jtable

    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.
  • Re: Jframe jtable

    Bene qua ci esce un ottimo barbeque (non so come si scrive) *_*
    ti ringrazio infinitamente per avermi spiegato meglio tutte queste cose.
    purtroppo ero in palestra (ma si può impiegarci 2h e mezza per una scheda????) quindi data l'ora non ho minimamente tempo di iniziare a fare i cambiamenti da te suggeriti (difatti sono dannatamente in ritardo per scuola). ma quando torno da scuola, visto il mio problema a prendere sonno, andrò sicuramente avanti fino alle 2-3 di notte. quando torno a casa rileggo con più calma e inizio a sistemare ^_^ ti ringrazio di nuovo per l'aiuto la pazienza e le spiegazioni
    @EDIT:
    bhe ma se quando voglio visualizzare entrambi i veicoli io voglio mostrare solo i 19 attributi comuni, le altre colonne son di troppo, le vorrei togliere. cioè a me fa brutto vedere delle colonne che non ci azzeccano nulla
  • Re: Jframe jtable

    KuroKami69 ha scritto:


    Bhe ma se quando voglio visualizzare entrambi i veicoli io voglio mostrare solo i 19 attributi comuni, le altre colonne son di troppo, le vorrei togliere. cioè a me fa brutto vedere delle colonne che non ci azzeccano nulla
    Per la visualizzazione mista a me non pare una brutta cosa che si veda tutto, semmai mi farebbe un po' strano vedere nella tabella colonne riferite alle automobili se sto visualizzando solo le moto o viceversa.

    Finché vai a toccare solo le righe la classe del modello rimane coerente e pulita, se cominci a lavorare sulle colonne ci vuole più attenzione.
    Ho solo visto esempi di colonne che vengono mostrate/nascoste attraverso il TableColumnModel, veniva però usato tutto un altro procedimento che non ti consiglio affatto, con una mappa di oggetti TableColumn, o in un altro caso una List <TableColumn> in modo ancora diverso, niente che preveda di usare direttamente il AbstractTableModel (o un suo derivato chiaramente).

    Questo per dire che non saprei consigliarti la soluzione migliore/più elegante, ma non è che non si possa fare. Devi però sincronizzare tutti i seguenti metodi:

    - Il getColumnCount() non può più ritornare la lunghezza del vettore di nomi delle colonne.
    - Il getColumnClass rimarrebbe invariato se volessi togliere solo le ultime n colonne, ma se ne vuoi togliere anche solo una precedente a un'altra visibile, va cambiato anche questo metodo.
    - Per getColumnName () vale lo stesso di quanto detto per getColumnClass ().
    - Infine anche il getValueAt () risente delle stesse modifiche dei due metodi precedenti.

    Se hai es. 10 colonne comuni, poi 5 colonne solo per le auto e 3 colonne solo per le moto, e vuoi vedere solo quelle comuni nel caso in cui la visualizzazione sia auto e moto, la soluzione sarebbe anche semplice:

    - il getColumnCount ritorna la lunghezza del vettore di colonne se la visualizzazione è solo auto o solo moto, o ritorna 10 se la visualizzazione è entrambi i veicoli.
    - getColumnClass e getColumnName non cambiano. Al massimo puoi ritornare null se viene passato un indice maggiore di 9 e sei nella visualizzazione mista, perché se il modello dichiara di avere 10 colonne in quel caso questi due metodi non dovrebbero essere richiamati con indici maggiori.
    - Nel getValueAt () fai una cosa simile. Gli indici si riferiranno sempre a metodi definiti in Veicolo, quindi se la visualizzazione è mista ritorni il metodo corretto se l'indice è tra 0 e 9, altrimenti ritorni null.

    Inserire così valori nel codice non mi sembra molto pulito, forse la cosa migliora un po' usando delle variabili, ma neanche tanto.

    Se poi tu volessi nascondere ad esempio le 5 colonne che riguardano le macchine quando la visualizzazione è solo moto, la cosa si complica di parecchio: oltre al getColumnCount che dovrebbe ritornare 13, ti si sfasano tutti gli indici dei vettori che hai definito.

    Prova a pensare: quando viene richiamato getColumnName (10) dalla JTable, che in quel momento "sa" (perché l'ha appena chiesto al modello) di avere 13 colonne e quindi di dover arrivare fino a 12 con le invocazioni, tu non devi più ritornare colonne[10], perché quel nome si riferisce alla prime delle 5 colonne che vuoi nascondere, dovresti restituire colonne [15]. Lo stesso vale per gli altri metodi.

    Potresti anche pensare di giocare con gli indici, ma la cosa è quantomeno rischiosa.

    Onestamente soluzioni semplici che non ti costringano a cambiare tutto il modello, o a fare cose parecchio discutibili non me ne vengono in mente, se qualcuno ha idee migliori, ben venga!
  • Re: Jframe jtable

    Se invece dovessi cambiare tutto il modello te avresti una soluzione raffinata?
Devi accedere o registrarti per scrivere nel forum
230 risposte