Problema con i checkbox nella JTable

di il
8 risposte

Problema con i checkbox nella JTable

Ciao, ho una tabella, che prende i dati da un database, la prima colonna della tabella però è un booleano che mi serve a capire quali righe sono di interesse per l'utente dopo che preme un pulsante. Ora il valore iniziale è false in modo che mi stampi un checkbox non spuntato, quando clicco sul checkbox ovviamente deve diventare true e spuntato, e ciò accade più o meno, nel senso che se clicco sulla riga di indice 0 funziona, ma se clicco su quella di indice 1 subito dopo aver cliccato su quella di indice 0 la spunta appare e scompare, e non cambia il valore che checkbox.

La tabella l'ho implementata così
ArrayList<Prodotto> listaProdotti = ProdottoBusiness.getInstance().findAll();
        TableModel model = new ListaProdottiTableModel(listaProdotti);
        JTable table = new JTable(model);
        table.setFillsViewportHeight(true);
        centro.add(new JScrollPane(table));
ListaProdottiTableModel.java
package it.progetto.model;

import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;

public class ListaProdottiTableModel extends AbstractTableModel {

    private ArrayList<Prodotto> listaprodotti;

    private final String[] header = {"", "Nome","Pezzo","Disponibilita'","Descrizione", "Sconto", "Produttore", "Distributore" };

    boolean selected=false;

    public ListaProdottiTableModel(ArrayList<Prodotto> listaprodotti){
        this.listaprodotti = listaprodotti;
    }

    // numero di righe
    public int getRowCount()
    {
        return listaprodotti.size();
    }

    // numero di colonne
    public int getColumnCount()
    {
        return header.length;
    }

    // nome di una determinata colonna
    @Override
    public String getColumnName(int columnIndex)
    {
        return header[columnIndex];
    }

    @Override
    public Class getColumnClass(int columnIndex) {
        if(columnIndex == 0 || columnIndex==3) return Boolean.class;
        if(columnIndex==2) return Float.class;
        return String.class;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Prodotto p = listaprodotti.get(rowIndex);

        switch (columnIndex){
            case 0: return selected;
            case 1: return p.getNome();
            case 2: return p.getPrezzo();
            case 3: return p.isDisponibile();
            case 4: return p.getDescrizione();
            case 5: return p.getPercentuale_sconto();
            case 6: return p.getIdProduttore();
            case 7: return p.getIdDistributore();
            default: return null;

        }
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return columnIndex==0;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        selected = (boolean) aValue;
        fireTableCellUpdated(rowIndex, columnIndex);
    }
}

8 Risposte

  • Re: Problema con i checkbox nella JTable

    simoorusso ha scritto:


    se clicco sulla riga di indice 0 funziona, ma se clicco su quella di indice 1 subito dopo aver cliccato su quella di indice 0 la spunta appare e scompare, e non cambia il valore che checkbox.
    Il punto è quello! Cioè quel tuo "selected" nel table model. Che è 1 variabile .... quindi? Se vuoi che ciascuna riga MANTENGA il SUO flag di selezione, devi avere lo storage apposito per i flag.

    Detto in altre parole, devi "affiancare" a ciascun oggetto Prodotto nel ArrayList un valore boolean. Non basta appunto 1 sola variabile!
    E come farlo ... ci sono diversi modi.
  • Re: Problema con i checkbox nella JTable

    Se creassi un array che contiene boolean, cioè se la variabile selected diventasse un array di boolean? Sarebbe una soluzione accettabile?
  • Re: Problema con i checkbox nella JTable

    simoorusso ha scritto:


    Se creassi un array che contiene boolean, cioè se la variabile selected diventasse un array di boolean? Sarebbe una soluzione accettabile?
    Tecnicamente sì, funzionerebbe. Sia come array:

    private ArrayList<Prodotto> listaprodotti;
    private boolean[] selected;

    o magari meglio come lista

    private ArrayList<Prodotto> listaprodotti;
    private ArrayList<Boolean> selected;

    Ripeto, tecnicamente funzionerebbe, come ho detto ma .... il punto è un altro: sarebbe abbastanza "brutto" e poco object oriented. Dovresti gestire 2 sequenze separate e tenerle sempre allineate.

    C'è una soluzione migliore. Crei una classe interna (nested class) privata nel table model, es. Elemento (nessuno dall'esterno ne saprebbe qualcosa) che "unisce" un prodotto e il suo flag.
    public class ListaProdottiTableModel extends AbstractTableModel {
    
        private ArrayList<Elemento> listaprodotti;
    
        // .....
    
        private static class Elemento {
            private Prodotto prodotto;
            private boolean selected;
    
            // ... getter/setter
        }
    }
    Devi ovviamente cambiare alcune cose (es. nel costruttore non basta più this.listaprodotti = listaprodotti; ) ma è relativamente poco (se sei arrivato fin qui, NON dovresti avere problemi/dubbi a riguardo) e se in futuro dovessi aggiungere qualcosa al Elemento, è abbastanza facile.


    Poi nel table model puoi anche aggiungere, per te che usi direttamente questo tuo table model, un metodo es.

    public List<Prodotto> getProdottiSelezionati()

    tutto lì ...
  • Re: Problema con i checkbox nella JTable

    Quindi se ho capito bene dopo aver creato la nested class Elemento, userò elemento invece di prodotto e quindi gli array di tipo prodotto saranno array di tipo elemento?
  • Re: Problema con i checkbox nella JTable

    simoorusso ha scritto:


    Quindi se ho capito bene dopo aver creato la nested class Elemento, userò elemento invece di prodotto e quindi gli array di tipo prodotto saranno array di tipo elemento?
    Sì, ma SOLO nel table model. Dall'esterno NON è detto (dimmelo tu se serve) che qualcuno debba "sapere" del Elemento nel table model.
  • Re: Problema con i checkbox nella JTable

    andbin ha scritto:


    Sì, ma SOLO nel table model.
    Sisi avevo capito che parlavamo solo del table model.

    andbin ha scritto:


    Dall'esterno NON è detto (dimmelo tu se serve) che qualcuno debba "sapere" del Elemento nel table model.
    Ho bisogno di prendere il valore di selected per salvare i Prodotti selezionati in seguito ma posso farlo dal table model con
    public ArrayList<Prodotto> getSelectedProduct()
    (che devo ancora implementare) che restituisce un'array contenente dati di tipo Prodotto, la richiamo dal listener in questo modo
    ArrayList<Prodotto> prodotti = table.getSelectedProduct
    però così non saprei come portarmi dietro un riferimento alla tabella, l'unica idea che ho è di usare
     "JTable jTable = (JTable) e.getSource()"
    potrebbe funzionare?

    Edit. Mi pare improbabile che funzioni, un'altra soluzione a cui ho pensato è di salvare la tabella in una SessionManager
  • Re: Problema con i checkbox nella JTable

    simoorusso ha scritto:


    Ho bisogno di prendere il valore di selected per salvare i Prodotti selezionati in seguito ma posso farlo dal table model con
    public ArrayList<Prodotto> getSelectedProduct()
    (che devo ancora implementare) che restituisce un'array contenente dati di tipo Prodotto, la richiamo dal listener in questo modo
    ArrayList<Prodotto> prodotti = table.getSelectedProduct
    però così non saprei come portarmi dietro un riferimento alla tabella, l'unica idea che ho è di usare
     "JTable jTable = (JTable) e.getSource()"
    potrebbe funzionare?
    Il riferimento al TUO table model, dovresti tenertelo come variabile di istanza da qualche parte (non so come è la tua architettura). E a quel punto "parli" solo con il tuo table model.
  • Re: Problema con i checkbox nella JTable

    Ok, ho capito, grazie mille
Devi accedere o registrarti per scrivere nel forum
8 risposte