Jframe jtable

di il
230 risposte

230 Risposte - Pagina 3

  • Re: Jframe jtable

    Il pack () serve per "impacchettare" il frame una volta che tutti i componenti sono stati aggiunti.
    Va quindi fatto subito prima di rendere visibile il frame (al limite tra le due cose puoi appunto settare una location sullo schermo al frame, come nel pseudo codice che avevo inserito).

    Prima aggiungi ogni elemento al frame (immagino tu ti riferisca a questo con "chiamare ogni singolo elemento") e lo rendi visibile solo dopo, il resto dei componenti è già visibile di default, non andrai quasi mai a dover specificare la visibilità di un pannello o di un bottone o quant'altro.
    Per le finestre invece devi settare tu la visibilità, ma se mancano dei componenti rischi solo rogne, tutto qui.

    Per il resto ok.
  • Re: Jframe jtable

    Ho editato tipo 3 volte il messaggio, ignorando che avessi risposto e si fosse creata una terza pagina, scusa :'D
    ho capito, indubbiamente ha senso quello che dici
    domanda puramente pratica: ho detto che mi piacerebbe che si potesse scegliere cosa visualizzare nella tabella. quindi: auto, moto, entrambi. è più pratico fare dei radiobutton oppure un piccolo menù a tendina?
  • Re: Jframe jtable

    KuroKami69 ha scritto:


    Ho editato tipo 3 volte il messaggio, ignorando che avessi risposto e si fosse creata una terza pagina, scusa :'D
    ho capito, indubbiamente ha senso quello che dici
    Mi sono perso solo la domanda sul cambiamento dello spinner, che comunque vale anche per l'aggiornamento della scelta auto/moto/entrambi.

    Hai almeno due soluzioni:

    - la prima è utilizzare un pulsante del tipo "Refresh" che una volta cliccato va a leggere il valore dello spinner e degli altri componenti (relativi a che veicoli mostrare o anche altro) e imposta la tabella in modo appropriato. Questa soluzione è più semplice e più leggera, perché i cambiamenti saranno relativamente pochi, ma non avrai un cambiamento "in tempo reale".
    - la seconda è utilizzare un ChangeListener che verrà aggiunto allo spinner e riceverà ogni evento, quindi potresti riaggiornare la tabella ad ogni modifica. A seconda dei componenti (tra quelli che cito dopo, per JSpinner usa il ChangeListener se segui questa via) possono cambiare leggermente i tipi di listener di questo tipo: JCheckBox e JRadioButton hanno la possibilità di aggiungere sia un ChangeListener sia un ItemListener, JComboBox non ha ChangeListener ma ha ItemListener, e tutti possono aggiungere un ActionListener.
    Io per i componenti che lo prevedono sono abituato ad usare l'ItemListener, ma le differenze non sono così marcate, ad esempio il ChangeListener dovrebbe lanciare più di un evento in corrispondenza di una selezione/delezione se non sbaglio.

    Scegli tu cosa fare, come detto la prima soluzione è più semplice, ti basta che nell'actionPerformed del bottone per aggiornare la tabella i reference degli altri componenti siano accessibili (quindi dichiarati come campi private della classe o come variabili locali nello stesso metodo in cui crei il listener del pulsante).
    La seconda potrebbe essere più carina, ma a me ad esempio vedere righe che si tolgono/aggiungono per ogni singolo incremento/decremento darebbe fastidio, mentre il filtraggio della tabella per auto/moto/entrambi preferirei che fosse immediato. Scegli tu.

    KuroKami69 ha scritto:


    domanda puramente pratica: ho detto che mi piacerebbe che si potesse scegliere cosa visualizzare nella tabella. quindi: auto, moto, entrambi. è più pratico fare dei radiobutton oppure un piccolo menù a tendina?
    Finché gli elementi sono in numero ragionevole è ancora una volta una scelta di gusto personale, un JComboBox è sicuramente più indicato quando gli elementi cominciano a essere di più, un JRadioButton con 7/8 alternative comincia già a perdere di efficacia. Con due/tre alternative va benissimo, scegli quello che preferisci, sono entrambi abbastanza semplici da usare, con la differenza che i JRadioButton hanno bisogno di essere aggiunti a un ButtonGroup per essere coordinati (cioè se tu selezioni uno quello selezionato in precedenza deve essere deselezionato), e che i listener vanno aggiunti su ogni bottone (così come per controllare quale è selezionato devi ciclare su tutti quelli che hai usando isSelected ()).
    Sopra ho parlato di JCheckBox perché sarebbe la mia scelta preferita in questo contesto, mi pare la migliore se le modalità non si escludono a vicenda, e se dovessi aggiungere un altro tipo di veicolo non avresti il problema di introdurre categorie come "solo auto e moto", "solo auto ibride e moto usate" o chi più ne ha più ne metta.
  • Re: Jframe jtable

    Ansharja ha scritto:


    KuroKami69 ha scritto:


    Ho editato tipo 3 volte il messaggio, ignorando che avessi risposto e si fosse creata una terza pagina, scusa :'D
    ho capito, indubbiamente ha senso quello che dici
    Mi sono perso solo la domanda sul cambiamento dello spinner, che comunque vale anche per l'aggiornamento della scelta auto/moto/entrambi.

    Hai almeno due soluzioni:

    - la prima è utilizzare un pulsante del tipo "Refresh" che una volta cliccato va a leggere il valore dello spinner e degli altri componenti (relativi a che veicoli mostrare o anche altro) e imposta la tabella in modo appropriato. Questa soluzione è più semplice e più leggera, perché i cambiamenti saranno relativamente pochi, ma non avrai un cambiamento "in tempo reale".
    - la seconda è utilizzare un ChangeListener che verrà aggiunto allo spinner e riceverà ogni evento, quindi potresti riaggiornare la tabella ad ogni modifica. A seconda dei componenti (tra quelli che cito dopo, per JSpinner usa il ChangeListener se segui questa via) possono cambiare leggermente i tipi di listener di questo tipo: JCheckBox e JRadioButton hanno la possibilità di aggiungere sia un ChangeListener sia un ItemListener, JComboBox non ha ChangeListener ma ha ItemListener, e tutti possono aggiungere un ActionListener.
    Io per i componenti che lo prevedono sono abituato ad usare l'ItemListener, ma le differenze non sono così marcate, ad esempio il ChangeListener dovrebbe lanciare più di un evento in corrispondenza di una selezione/delezione se non sbaglio.

    Scegli tu cosa fare, come detto la prima soluzione è più semplice, ti basta che nell'actionPerformed del bottone per aggiornare la tabella i reference degli altri componenti siano accessibili (quindi dichiarati come campi private della classe o come variabili locali nello stesso metodo in cui crei il listener del pulsante).
    La seconda potrebbe essere più carina, ma a me ad esempio vedere righe che si tolgono/aggiungono per ogni singolo incremento/decremento darebbe fastidio, mentre il filtraggio della tabella per auto/moto/entrambi preferirei che fosse immediato. Scegli tu.
    bhe ho provato ad associare allo spinner il bottone, ma mi ha dato errore mmh quindi ho pensato non si potesse fare.
    (e ora ho cancellato il codice relativo al bottone)
    essendo una cosa scolastica effettivamente mi piacerebbe mostrare entrambe le soluzioni, il cambiamento al click, e quello in tempo reale scegliendo cosa visualizzare
    posso chiederti di farmi un esempio di codice di spinner che si appoggia a un bottone per favore?
    il mio attuale spinner è il seguente:
    
    JSpinner js = new JSpinner(jsm);
    		js.addChangeListener(new ChangeListener()
    		{
    			public void stateChanged(ChangeEvent e)
    			{
    				Object i = ((JSpinner)e.getSource()).getValue();
    				//JOptionPane.showMessageDialog(null, "hai digitato " + ((JSpinner)e.getSource()).getValue(), "allert", JOptionPane.INFORMATION_MESSAGE);
    				JOptionPane.showMessageDialog(null, i);
    			}
    		});
    
    dove la i la passo poi al ciclo che mi popola la tabella, ora sto solo facendo delle prove per vedere se funziona tutto quindi uso un output
    prima se non sbaglio avevo
    
    JButton b = new JButton("Visualizza");
    b.addActionListener(new ActionListener()
          {
             public void actionPerformed(ActionEvent e)
             {
                int i = Integer.parseInt(jt.getText());
                //JOptionPane.showMessageDialog(null, "hai digitato " + i, "allert", JOptionPane.INFORMATION_MESSAGE);
             }
          });
    
    ho provato ad associare questo bottone allo spinner ma mi ha dato errore, ma ora non ricordo il codice che ho usato ahahaha
    comunque se potessi farmi un esempio di come associare questi 2 elementi te ne sarei grato

    Ansharja ha scritto:


    KuroKami69 ha scritto:


    domanda puramente pratica: ho detto che mi piacerebbe che si potesse scegliere cosa visualizzare nella tabella. quindi: auto, moto, entrambi. è più pratico fare dei radiobutton oppure un piccolo menù a tendina?
    Finché gli elementi sono in numero ragionevole è ancora una volta una scelta di gusto personale, un JComboBox è sicuramente più indicato quando gli elementi cominciano a essere di più, un JRadioButton con 7/8 alternative comincia già a perdere di efficacia. Con due/tre alternative va benissimo, scegli quello che preferisci, sono entrambi abbastanza semplici da usare, con la differenza che i JRadioButton hanno bisogno di essere aggiunti a un ButtonGroup per essere coordinati (cioè se tu selezioni uno quello selezionato in precedenza deve essere deselezionato), e che i listener vanno aggiunti su ogni bottone (così come per controllare quale è selezionato devi ciclare su tutti quelli che hai usando isSelected ()).
    il funzionamento dei radio è lo stesso di quelli di html tipo giusto?

    Ansharja ha scritto:


    Sopra ho parlato di JCheckBox perché sarebbe la mia scelta preferita in questo contesto, mi pare la migliore se le modalità non si escludono a vicenda, e se dovessi aggiungere un altro tipo di veicolo non avresti il problema di introdurre categorie come "solo auto e moto", "solo auto ibride e moto usate" o chi più ne ha più ne metta.
    onestamente non ho capito come vorresti usare il jcheckbox.
    volevo implementarne uno che, una volta spuntato converte i cavalli in kw, quindi mi trasforma tutta la colonna cavalli in kw, cambiando anche nome se possibile xD
    non intendo implementare altri mezzi, quindi le opzioni rimangono 3 mmh
    ora, domanda:
    ho creato la mia arraylist popolandola con tante Automobili.
    al momento non so come fare il binding, non ho capito se esiste un metodo ufficiale oracle, diciamo, oppure se devo prenderne uno fatto da altri, come quello che ho linkato prima, se ho capito bene.
    fino a quando non ho una binding solution, per poter popolare la mia tabella, devo farmi un array di n posti, e ad ogni posto assegnare un metodo get della mia classe automobile, e poi inserirlo in 2 for per popolare la tabella, corretto? un'altra cosa.
    la mia classe tabella devo aggiungere extend AbstractTabelModel vero?
  • Re: Jframe jtable

    Ho trovato questo video
    è una buona soluzione? mi son perso circa a metà ma rivedendolo un altro paio di volte non dovrei avere difficoltà a capire
    onestamente non ho capito se la posso adattare al mio problema mmh
  • Re: Jframe jtable

    KuroKami69 ha scritto:


    Ho trovato questo video
    è una buona soluzione? mi son perso circa a metà ma rivedendolo un altro paio di volte non dovrei avere difficoltà a capire
    onestamente non ho capito se la posso adattare al mio problema mmh
    @KuroKami69, forse l'avevo già detto ... lascia perdere i "video", lasciano il tempo che trovano ...

    Stai facendo un miscuglio di cose, tra JTable, table model, "binding", spinner, pack() ecc... E non hai ancora delle "basi" valide (né su Swing né su Java in generale). Ora: se vuoi potrei anche farti un esempio basilare d'uso di un table model specializzato (esempio di 3 classi in croce) però poi bisogna vedere cosa riesci a comprendere.
  • Re: Jframe jtable

    KuroKami69 ha scritto:


    posso chiederti di farmi un esempio di codice di spinner che si appoggia a un bottone per favore?
    [...]
    comunque se potessi farmi un esempio di come associare questi 2 elementi te ne sarei grato
    Non è che lo spinner si appoggi al bottone, hai solo bisogno di utilizzare il getValue () dello spinner per leggerne il valore all'interno dell'actionPerformed del bottone.
    
    final JSpinner spinner = new JSpinner (/* ... */);
    // ...
    JButton button = new JButton (/* ... */);
    button.addActionListener (new ActionListener () {
    	public void actionPerformed (ActionEvent e) {
    		Object value = spinner.getValue ();
    		// Se usi uno SpinnerNumberModel puoi fare il cast a Integer senza rischi
    		Integer rows = (Integer) value;
    		// ... Fai quello che vuoi con rows ...
    	}
    });
    
    Se lo spinner non è variabile d'istanza della classe, ma è dichiarato localmente nel metodo dove crei il bottone, deve essere dichiarato prima del bottone ed essere final, altrimenti non potrai accederci all'interno della classe anonima che implementa ActionListener (da java8 in poi ti basta che sia "effectively final", ovvero se non ci assegni un altro oggetto in seguito non avrai errori dal compilatore).
    Ti dico questo solo per evitarti errori in compilazione, ad ora non è fondamentale che tu capisca questi particolari.

    KuroKami69 ha scritto:


    Il funzionamento dei radio è lo stesso di quelli di html tipo giusto?
    In generale credo proprio di sì, non sono ferrato in Html, cambia il concetto che in swing hai bisogno del ButtonGroup per legarli, forse in html bastava dare loro lo stesso attributo name (da una ricerca rapidissima, come detto non sono ferrato).

    KuroKami69 ha scritto:


    onestamente non ho capito come vorresti usare il jcheckbox.
    volevo implementarne uno che, una volta spuntato converte i cavalli in kw, quindi mi trasforma tutta la colonna cavalli in kw, cambiando anche nome se possibile xD
    Ti basta controllare quando aggiornerai la tabella se i checkbox sono selezionati richiamando su di loro il metodo isSelected (). Se sono selezionati mostrerai le righe corrispondenti, altrimenti no.
    Filtrare la tabella non è immediato, ti consiglio di pensare prima al resto.

    KuroKami69 ha scritto:


    ho creato la mia arraylist popolandola con tante Automobili.
    al momento non so come fare il binding, non ho capito se esiste un metodo ufficiale oracle, diciamo, oppure se devo prenderne uno fatto da altri, come quello che ho linkato prima, se ho capito bene.
    fino a quando non ho una binding solution, per poter popolare la mia tabella, devo farmi un array di n posti, e ad ogni posto assegnare un metodo get della mia classe automobile, e poi inserirlo in 2 for per popolare la tabella, corretto? un'altra cosa.
    la mia classe tabella devo aggiungere extend AbstractTabelModel vero?
    Lascia stare il binding, fatti una semplice tabella prima, i costruttori di JTable e di DefaultTableModel sono più che sufficienti alle tue esigenze (e onestamente non ho nessuna voglia di mettermi a guardare video o leggermi la documentazione di classi esterne al framework) ...

    Immagina di avere una classe Auto con i seguenti attributi: cilindrata, marca e prezzo, e relativi metodi get (ovviamente ne scrivo tre per semplicità, non cambia nulla con più attributi), e di volere costruire una tabella con le colonne "Prezzo", "Cilindrata" e "Marca", popolando le righe da una lista di oggetti Auto, chiamiamola listaAutomobili.

    Questo è un semplice esempio di come farlo con DefaultTableModel, se vuoi usare un tuo modello che estende AbstractTableModel fa pure, ma non è la tabella che estende il modello:
    
    // arrivi qui con un ArrayList <Auto> listaAutomobili, preso come ti pare.
    
    Object [] columnNames = {"Prezzo", "Cilindrata", "Marca"};
    DefaultTableModel model = new DefaultTableModel (columnNames, 0);
    for (Auto auto : listaAutomobili) {
    	Object [] rowData = new Object [3];
    	rowData [0] = auto.getPrezzo ();
    	rowData [1] = auto.getCilindrata ();
    	rowData [2] = auto.getMarca ();
    	model.addRow (rowData);
    }
    JTable table = new JTable (model);
    
    Questo è un esempio basico, magari usare Object non sarà il massimo, e con un tuo modello potresti essere più fine, ma questo è un punto di partenza, puoi adattarlo al tuo caso.

    Trovi tutto questo nella documentazione, e nei tutorial che già conosci.
    Se vuoi imparare swing su internet non puoi andare avanti senza capire la documentazione, qui ti possiamo aiutare per problemi specifici o consigli su aspetti anche generali, ma devi riuscire a procedere in maniera un po' autonoma perché i componenti sono tanti e le cose da sapere ancora di più

    EDIT: Modificato il parametro rowCount passato al costruttore del DefaultTableModel, se usi addRow () non devi specificare da prima il numero di righe.
  • Re: Jframe jtable

    @andbin io sono come una spugna, se hai voglia di farmi un esempio e spiegare le varie parti (basta anche un semplice commento "qua uso questo per fare questo") io imparo generalmente per me è sempre stato così. Imparo con la pratica, e voi mi stato dando una mano enorme. Difatti ho capito perchè il bottone che avevo associato allo spinner non andava

    @Ansharja per il bottone avevo fatto un'assegnazione diversa del valore dello spinner, probabilmente è per questo che non me lo prendeva, ti ringrazio per l'esempio.
    Infatti ora mi concentro sulla sua popolazione, poi sul funzionamento delle varie "funzionalitá".
    Riguardo all'arraylist, avendo tipo 25 parametri, per forza di cose devo assegnare 25 metodi alle relative colonne giusto? Quindi prima faccio questo passo e poi popolo con 2 for annidati.
    oppure posso fare come hai suggerito te, di farlo con un unico for mmh
    E ripeto, io imparo molto di più provando, sbagliando e capendo perchè sbaglio, che facendo prima la teoria. Esempio
    Se mi passi un codice commentato inerente creazione e gestione di una tabella, non lo capisco tutto, però provando a replicarlo per i miei utilizzi, vedo i vari errori e arrivo a capire il funzionamento
    Se invece prima leggessi soltanto la documentazione, bhe si capirei ma avrei molte più difficoltá ad applicare perchè non ho un esempio pratico di base.
    Ora mi direte che come "sono impostato" io allo studio della programmazione, non è corretto, e bon voglio assolutamente dire il contrario, però ormai è così radicato in me questo metodo di apprendimento che non riesco a fare diversamente. Forse non mi spiego bene, forse si, spero capiate
  • Re: Jframe jtable

    KuroKami69 ha scritto:


    Riguardo all'arraylist, avendo tipo 25 parametri, per forza di cose devo assegnare 25 metodi alle relative colonne giusto? Quindi prima faccio questo passo e poi popolo con 2 for annidati.
    Non è che devi associare un metodo alla colonna, puoi immaginartelo così se ti viene comodo, ma se riguardi il mio codice vedi che semplicemente inserisco il valore di ogni attributo nell'indice corrispondente alla colonna, usando il corrispondente get.

    Questa parte non la puoi fare con un for annidato, non è che puoi inventarti un for interno che cicla da 0 a 24 e prende ogni singolo attributo, o qui o nel tuo modello devi prendere ogni attributo con il corrispondente get.
    Tecnicamente potresti anche evitare di farlo, ma faresti delle porcate indicibili (almeno secondo me, accetto volentieri correzioni da chi ne sa di più).
  • Re: Jframe jtable

    Ansharja ha scritto:


    KuroKami69 ha scritto:


    Riguardo all'arraylist, avendo tipo 25 parametri, per forza di cose devo assegnare 25 metodi alle relative colonne giusto? Quindi prima faccio questo passo e poi popolo con 2 for annidati.
    Non è che devi associare un metodo alla colonna, puoi immaginartelo così se ti viene comodo, ma se riguardi il mio codice vedi che semplicemente inserisco il valore di ogni attributo nell'indice corrispondente alla colonna, usando il corrispondente get.

    Questa parte non la puoi fare con un for annidato, non è che puoi inventarti un for interno che cicla da 0 a 24 e prende ogni singolo attributo, o qui o nel tuo modello devi prendere ogni attributo con il corrispondente get.
    Tecnicamente potresti anche evitare di farlo, ma faresti delle porcate indicibili (almeno secondo me, accetto volentieri correzioni da chi ne sa di più).
    scusami, credo proprio mi sfugga qualcosa allora
    mentre scrivevo ho capito dove sbagliavo. io stavo ragionando: "creo una matrice contenente tutti i valori da mostrare e poi la passo alla tabella"
    con il tuo codice invece a seconda di quanti veicoli voglio mostrare, mi crea una nuova riga, direttamente nella tabella, con i valori per ogni colonna giusto?
  • Re: Jframe jtable

    Ecco un esempio completo ma minimale e stringato davvero al minimo. Si tratta di 3 classi "in croce" con una implementazione specializzata di un table model che estende AbstractTableModel.
    public class Automobile {
        private String marca;
        private String modello;
        private int anno;
    
        public Automobile(String marca, String modello, int anno) {
            this.marca = marca;
            this.modello = modello;
            this.anno = anno;
        }
    
        public String getMarca() {
            return marca;
        }
    
        public void setMarca(String marca) {
            this.marca = marca;
        }
    
        public String getModello() {
            return modello;
        }
    
        public void setModello(String modello) {
            this.modello = modello;
        }
    
        public int getAnno() {
            return anno;
        }
    
        public void setAnno(int anno) {
            this.anno = anno;
        }
    }
    import java.util.List;
    import javax.swing.table.AbstractTableModel;
    
    public class AutomobileTableModel extends AbstractTableModel {
        private static final String[] nomiColonne = { "Marca", "Modello", "Anno" };
        private static final Class<?>[] tipiColonne = { String.class, String.class, Integer.class };
    
        private List<Automobile> automobili;
    
        public AutomobileTableModel(List<Automobile> automobili) {
            this.automobili = automobili;
        }
    
        @Override
        public String getColumnName(int columnIndex) {
            return nomiColonne[columnIndex];  // espone il nome alla tal colonna
        }
    
        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return tipiColonne[columnIndex];  // espone il tipo alla tal colonna
        }
    
        @Override
        public int getRowCount() {
            return automobili.size();  // espone il numero di righe (È il numero di elementi nella lista)
        }
    
        @Override
        public int getColumnCount() {
            return nomiColonne.length;  // espone il numero di colonne (È il numero di nomi)
        }
    
        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Automobile automobile = automobili.get(rowIndex);
    
            switch (columnIndex) {
            case 0: return automobile.getMarca();
            case 1: return automobile.getModello();
            case 2: return automobile.getAnno();
            default: return null;   // non dovrebbe succedere
            }
        }
    }
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.SwingUtilities;
    
    public class FrameTabellaAutomobili extends JFrame {
        private AutomobileTableModel tableModel;
        private JTable table;
        private JScrollPane scrollPane;
    
        public FrameTabellaAutomobili() {
            super("Tabella Automobili");
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setSize(400, 300);
            setLocationRelativeTo(null);
    
            List<Automobile> automobili = new ArrayList<Automobile>();
            automobili.add(new Automobile("Fiat", "Punto", 2013));
            automobili.add(new Automobile("Seat", "Ibiza", 2010));
            automobili.add(new Automobile("Lancia", "Delta", 2005));
    
            tableModel = new AutomobileTableModel(automobili);
            table = new JTable(tableModel);
            scrollPane = new JScrollPane(table);
    
            add(scrollPane);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new FrameTabellaAutomobili().setVisible(true);
                }
            });
        }
    }
    La classe Automobile è banale, non credo di doverla nemmeno "spiegare". Ha 3 campi, 1 costruttore e i getter/setter. Tra l'altro questi ultimi li faccio generalmente creare da Eclipse a partire dai field, che vengono perfetti come si deve.

    La classe AutomobileTableModel è il table model personalizzato.

    La classe FrameTabellaAutomobili è un semplice frame che contiene la tabella (dentro un JScrollPane perché potenzialmente scrollabile).

    Non guardate nomi/anni delle auto ... non me ne intendo di auto!

    Per qualunque dubbio ... chiedere.
  • Re: Jframe jtable

    KuroKami69 ha scritto:


    scusami, credo proprio mi sfugga qualcosa allora
    mentre scrivevo ho capito dove sbagliavo. io stavo ragionando: "creo una matrice contenente tutti i valori da mostrare e poi la passo alla tabella"
    con il tuo codice invece a seconda di quanti veicoli voglio mostrare, mi crea una nuova riga, direttamente nella tabella, con i valori per ogni colonna giusto?
    Con quel codice lì il modello aggiunge una riga alla volta, esatto, quindi volendo potresti anche usare questo per mostrare solo i primi "n" risultati.
    La riga non viene creata nella tabella, il modello prende il nuovo vettore di valori da inserire nella riga e internamente aggiorna la propria struttura dati, che poi viene passata alla tabella quando passi il modello al suo costruttore.
    La struttura dati immaginala pure come una matrice di dati per comodità, ma internamente DefaultTableModel utilizza un Vector, e quando aggiungi una riga (come nel mio codice) viene richiamato questo metodo:
    
    protected static Vector convertToVector(Object[] anArray) {
            if (anArray == null) {
                return null;
            }
            Vector<Object> v = new Vector<Object>(anArray.length);
            for (Object o : anArray) {
                v.addElement(o);
            }
            return v;
        }
    
    Questo solo per dirti che se vuoi puoi anche "sbirciare" nei sorgenti delle classi per vedere come funzionano dietro le quinte, per ora puoi tranquilissimamente fregartene.

    Se vuoi creare una matrice dati per poi passarla alla tabella (usando un costruttore JTable(Object[][] rowData, Object[] columnNames) che prende matrice di dati e vettore con i nomi delle colonne, che saranno "girati" al modello della tabella) puoi farlo, ma anche qui non userai un for annidato, il procedimento sarebbe qualcosa di questo tipo, sempre immaginando di avere una ArrayList <Auto> chiamata listaAuto:
    
    Object [][] rowData = new Object [colorList.size ()][3]; // dove tre sono le tue colonne, tu ne avrai di più
    Object [] columnNames = {"Prezzo", "Cilindrata", "Marca"};
    for (int i = 0; i < listaAutomobili.size (); i ++) {
    	Auto auto = listaAutomobili.get (i);
    	rowData [i][0] = auto.getPrezzo ();
    	rowData [i][1] = auto.getCilindrata ();
    	rowData [i][2] = auto.getMarca ();
    	// ... altri valori se ne hai 25
    }
    JTable table = new JTable (rowData, columnNames);
    
    Come vedi non c'è grande differenza, qui però non hai il controllo sul modello utilizzato dalla tabella.

    Il metodo che ti ha suggerito @andbin è ovviamente preferibile, è un po' più complicato e devi scrivere più codice, ma se lo capisci ti permette di avere molto più controllo sul modello.
    Ad esempio con il addRow (Object [] rowData) non sai cosa succede se inserisci un vettore con un numero di elementi diverso dal numero di colonne, e puoi passare degli Object quindi anche Banane alla tua tabella di Automobili.
    Con un modello personalizzato questo non succede.

    Guarda però cosa fa il suo getValueAt(int rowIndex, int columnIndex).
    Prende l'oggetto Automobile al dovuto indice della propria struttura dati, e poi fa uno switch sull'indice della colonna.
    In ogni case viene richiamato il get per ritornare il valore del campo corrispondente all'intestazione della colonna.
    Nel tuo caso quindi arriverai fino al case 24, e richiamerai tutti i 25 get, in un modo o nell'altro questo devi farlo, non si scappa e non si usa un doppio ciclo in nessun caso.
  • Re: Jframe jtable

    andbin ha scritto:


    Ecco un esempio completo ma minimale e stringato davvero al minimo. Si tratta di 3 classi "in croce" con una implementazione specializzata di un table model che estende AbstractTableModel.
    import java.util.List;
    import javax.swing.table.AbstractTableModel;
    
    public class AutomobileTableModel extends AbstractTableModel {
        private static final String[] nomiColonne = { "Marca", "Modello", "Anno" };
        private static final Class<?>[] tipiColonne = { String.class, String.class, Integer.class };
    
        private List<Automobile> automobili;
    
        public AutomobileTableModel(List<Automobile> automobili) {
            this.automobili = automobili;
        }
    
        @Override
        public String getColumnName(int columnIndex) {
            return nomiColonne[columnIndex];  // espone il nome alla tal colonna
        }
    
        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return tipiColonne[columnIndex];  // espone il tipo alla tal colonna
        }
    
        @Override
        public int getRowCount() {
            return automobili.size();  // espone il numero di righe (È il numero di elementi nella lista)
        }
    
        @Override
        public int getColumnCount() {
            return nomiColonne.length;  // espone il numero di colonne (È il numero di nomi)
        }
    
        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Automobile automobile = automobili.get(rowIndex);
    
            switch (columnIndex) {
            case 0: return automobile.getMarca();
            case 1: return automobile.getModello();
            case 2: return automobile.getAnno();
            default: return null;   // non dovrebbe succedere
            }
        }
    }
    ok ho capito si e no la metà di cosa fa questa classe! sostanzialmente hai creato una lista contenente n automobili (dove l'n a me verrà dato al listener dello spinner)
    ma poi non capisco come popoli la tabella mmmh anche se rileggendo un'idea me la sto facendo. a seconda di quanti elementi ha la lista, ricavi il numero di righe della tabella. poi a seconda di quante voci ha l'array nomi colonne definisci il numero di colonne della tabella.
    passi questi dato a getvalueat, che sostanzialmente è il metodo di visualizzazione, non so come chiamarlo, della tabella. e con uno switch fai il bind sostanzialmente. credo almeno

    andbin ha scritto:


    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.SwingUtilities;
    
    public class FrameTabellaAutomobili extends JFrame {
        private AutomobileTableModel tableModel;
        private JTable table;
        private JScrollPane scrollPane;
    
        public FrameTabellaAutomobili() {
            super("Tabella Automobili");
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setSize(400, 300);
            setLocationRelativeTo(null);
    
            List<Automobile> automobili = new ArrayList<Automobile>();
            automobili.add(new Automobile("Fiat", "Punto", 2013));
            automobili.add(new Automobile("Seat", "Ibiza", 2010));
            automobili.add(new Automobile("Lancia", "Delta", 2005));
    
            tableModel = new AutomobileTableModel(automobili);
            table = new JTable(tableModel);
            scrollPane = new JScrollPane(table);
    
            add(scrollPane);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new FrameTabellaAutomobili().setVisible(true);
                }
            });
        }
    }
    quel run non ho capito a cosa serve
    in questa classe qua comunque popoli la lista, crei la tabella, che si comporterà secondo il modello definito, e la butti nel frame che poi rendi visibile all'esecuzione giusto?

    andbin ha scritto:


    La classe Automobile è banale, non credo di doverla nemmeno "spiegare". Ha 3 campi, 1 costruttore e i getter/setter. Tra l'altro questi ultimi li faccio generalmente creare da Eclipse a partire dai field, che vengono perfetti come si deve.

    La classe AutomobileTableModel è il table model personalizzato.

    La classe FrameTabellaAutomobili è un semplice frame che contiene la tabella (dentro un JScrollPane perché potenzialmente scrollabile).

    Non guardate nomi/anni delle auto ... non me ne intendo di auto!

    Per qualunque dubbio ... chiedere.
    certo, io chiedo sempre quando non capisco, non ho problemi ad ammettere la mia ignoranza quando effettivamente non so!
    grazie mille per la soluzione, mi ci metterò di impegno per capirla, e poi, se ho il tuo permesso, per provare ad implementarla nel mio lavoro

    @Ansharja
    io mi ero immaginato una struttura simile
    
    Object[] arrayMetodi = new Object[25];
    Object[][]data = new Object[n][25]; //dove n mi viene dato dal listener dello spinner
    arrayMetodi[0] = auto.getModello();
    arrayMetodi[1] = auto.getStato();
    arrayMetodi[2] = auto.getMarca();
    arrayMetodi[3] = auto.getColore();
    arrayMetodi[4] = auto.getTipo();
    arrayMetodi[5] = auto.getCilindri();
    arrayMetodi[6] = auto.getCavalli();
    
    //quindi essendo io babbo ho pensato così i for:
    for (int i = 0; i <= 25; i++) //colonne
    {
    for (int k = 0; k <= n; k++) //righe
    {
    data[i][k] = arrayMetodi[i]; //data[0][0,1,2,3,4 ecc] = getModello(); quindi mi popolerà tante righe quante auto creo
    }
    }
    
    avevo pensato a una cosa simile ecco.
    forse è inefficiente perché non credo mi permetta di avere una tabella dinamica, o forse si? cioè se io decido di vedere 25 auto anziché 20, o se decido di voler vedere le moto, dovrà ricrearmi la matrice da 0 e non va bene. con il metodo di andbin invece semplicemente aggiungo e tolgo righe a piacimento senza problemi

    se sto dicendo cose senza senso fermatemi per piacere!
  • Re: Jframe jtable

    Domanda
    stavo provando a mettere il listener al JCheckBox, e ovviamente non sapendo quasi nulla, sto guardando qua e la online come si fa.
    ho trovato questo esempio di codice
    
    checkbox.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent event) {
            JCheckBox cb = (JCheckBox) event.getSource();
            if (cb.isSelected()) {
                // do something if check box is selected
            } else {
                // check box is unselected, do something else
            }
        }
    });
    
    versione completa
    sostanzialmente ho fatto la stessa cosa, solo che ho chiamato il mio checkbox cb
    
    cb.addActionListener(new ActionListener()
    		{
    			@Override
    			public void ActionPerformed(ActionEvent e)
    			{
    				JCheckBox c = (JCheckBox)e.getSource();
    				if(c.isSelected())
    				JOptionPane.showMessageDialog(null, "selezionato");
    				else
    				JOptionPane.showMessageDialog(null, "deselezionato");
    			}
    		});
    
    perché mi da questo errore?
    
    Salone.java:68: error: <anonymous Salone$1> is not abstract and does not overrid
    e abstract method actionPerformed(ActionEvent) in ActionListener
                    {
                    ^
    
    p.s. a me interessava chiamare il metodo di conversione in kw dei cavalli, alla spunta del box, e ricaricare i valori in cavalli togliendo la spunta. è meglio usare l'action handler?
  • Re: Jframe jtable

    KuroKami69 ha scritto:


    ok ho capito si e no la metà di cosa fa questa classe! sostanzialmente hai creato una lista contenente n automobili (dove l'n a me verrà dato al listener dello spinner)
    ma poi non capisco come popoli la tabella mmmh anche se rileggendo un'idea me la sto facendo. a seconda di quanti elementi ha la lista, ricavi il numero di righe della tabella. poi a seconda di quante voci ha l'array nomi colonne definisci il numero di colonne della tabella.
    passi questi dato a getvalueat, che sostanzialmente è il metodo di visualizzazione, non so come chiamarlo, della tabella. e con uno switch fai il bind sostanzialmente. credo almeno
    Se ti ricordi cosa dicevo all'inizio, JTable non "sa" nulla di come è fatta la tabella e cosa contenga. JTable va a "chiedere" tutto quanto al table model. Durante il ciclo di vita della tabella, JTable andrà a chiedere in sequenza anche più volte quelle informazioni. In quale ordine e quando .... NON è granché importante. Si potrebbe andare a vedere i sorgenti del framework per i dettagli. Ma ripeto: se anche non lo sai, NON importa.

    Si può fare al massimo qualche ragionamento. È abbastanza logico pensare che getRowCount()/getColumnCount() verranno chiamati PRIMA di chiamare più volte il getValueAt(). Bisogna ovviamente capire quanto è grande la tabella prima di accedere ai dati, altrimenti non saprebbe fino a che indici è possibile arrivare!

    KuroKami69 ha scritto:


    quel run non ho capito a cosa serve
    Il invokeLater serve per far eseguire il run() di un Runnable nel contesto del Event Dispatch Thread (EDT). Usato così nel main serve per far partire tutta la creazione della GUI già nel contesto del EDT e non del "main" thread.
    Se non sai cosa è il EDT .... bene (cioè .. male), è un'altra cosa importante che dovresti poi apprendere. Ma per il momento potresti anche ignorarla se non si tira in ballo il multi-threading.

    KuroKami69 ha scritto:


    in questa classe qua comunque popoli la lista, crei la tabella, che si comporterà secondo il modello definito, e la butti nel frame che poi rendi visibile all'esecuzione giusto?
    Sostanzialmente sì.
Devi accedere o registrarti per scrivere nel forum
230 risposte