PDA

View Full Version : [JAVA] JTable & JComboBox


DigitalKiller
29-06-2007, 14:19
E' da alcuni giorni che sto provando a risolvere un problema con una jtable senza riuscirci.
Nel programma che sto scrivendo, vado a leggere la tabella UTENTI di un database Mysql. All'interno di questa tabella c'è un campo di tipo VARCHAR il cui contenuto è true o false che mi indica se un utente è abilitato o meno. Quello che voglio fare, è visualizzare i record in una jtable e, per la colonna ABILITATo, visualizzare una checkbox.

Ho creato una classe generica per la gestione (connessione, query, ecc) del database a cui passo una stringa sql (es. SELECT * FROM UTENTI) ottendendo come valore di ritorno un vettore contenente tutti i record selezionati. Questo è una parte del codice della classe Database.java:

while(rs.next()) {
record = new Vector();
for (int i = 0; i < colonne; i++) {
record.add(rs.getString(i + 1));
}
v.add(record.clone());
}

Il vettore ritornato, lo passo al costruttore della classe TabellaSolaLettura che estende DefaultTableModel. Questa è la classe TabellaSolaLettura.java:

public TabellaSolaLettura(Vector tabellaDati, Vector tabellaNomColonne) {
super(tabellaDati, tabellaNomColonne);
}

public boolean isCellEditable(int riga, int colonna) {
return false;
}

public Class getColumnClass(int colonna) {
return getValueAt(0, colonna).getClass();
}

In questo modo, i record letti dal database vengono visualizzati correttamente ma per la colonna ABILITATO vengono visualizzati i valori letti, cioè true o false. Il problema è che tutti i record sono letti come stringhe e quindi il metodo getColumnClass(int colonna) mi restituisce sempre String. Ho modificato il metodo in questo modo:

public Class getColumnClass(int colonna) {
switch (colonna) {
case 7:
return Boolean.class;
default:
return getValueAt(0, colonna).getClass();
}
}

ma ottengo questa eccezione java.lang.String cannot be cast to java.lang.Boolean.
Come posso risolvere?:help:

andbin
29-06-2007, 14:32
ma ottengo questa eccezione java.lang.String cannot be cast to java.lang.Boolean.
Come posso risolvere?:help:Come dici tu, quel campo ce l'hai come stringa. Tecnicamente non è sbagliato far ritornare in modo forzato Boolean.class nel caso della colonna 7 ma il succo è che quel campo è comunque ancora un String!

Se nel campo puoi avere "true" oppure "false", Allora crea un Boolean (e c'è un costruttore di Boolean apposito che prende un String).

DigitalKiller
29-06-2007, 14:41
Come dici tu, quel campo ce l'hai come stringa. Tecnicamente non è sbagliato far ritornare in modo forzato Boolean.class nel caso della colonna 7 ma il succo è che quel campo è comunque ancora un String!

Se nel campo puoi avere "true" oppure "false", Allora crea un Boolean (e c'è un costruttore di Boolean apposito che prende un String).

Intendi una cosa del genere?
public Class getColumnClass(int colonna) {
switch (colonna) {
case 7:
//return Boolean.class;
Boolean abilitato = new Boolean(getValueAt(0, colonna).toString());
return abilitato.getClass();
default:
return getValueAt(0, colonna).getClass();
}
}

Se si, avevo già provato come soluzione ma ho sempre la stessa eccezione:muro:

andbin
29-06-2007, 15:00
Intendi una cosa del genere?No, nel tuo Vector del record devi avere un Boolean se in getColumnClass fai ritornare un Boolean.class per quel valore!

DigitalKiller
29-06-2007, 15:19
No, nel tuo Vector del record devi avere un Boolean se in getColumnClass fai ritornare un Boolean.class per quel valore!

Scusami, potresti essere più chiaro? Non sto riuscendo a capire:(

andbin
29-06-2007, 15:25
Scusami, potresti essere più chiaro? Non sto riuscendo a capire:(while(rs.next()) {
record = new Vector();
for (int i = 0; i < colonne; i++) {
record.add(rs.getString(i + 1));
}
v.add(record.clone());
}Così metti nel Vector sempre e comunque delle String. Per quel campo dove hai true/false, nel Vector devi mettere un Boolean.

DigitalKiller
29-06-2007, 15:31
while(rs.next()) {
record = new Vector();
for (int i = 0; i < colonne; i++) {
record.add(rs.getString(i + 1));
}
v.add(record.clone());
}Così metti nel Vector sempre e comunque delle String. Per quel campo dove hai true/false, nel Vector devi mettere un Boolean.

Ho modificato il codice in questo modo, senza fare riferimento al numero della colonna. Così posso riutilizzare il metodo anche in altre classi del programma:sofico:
for (int i = 0; i < colonne; i++) {
if (rs.getString(i + 1).equals("true") || rs.getString(i + 1).equals("false")) {
record.add(rs.getBoolean(i + 1));
} else {
record.add(rs.getString(i + 1));
}
}

Che ne pensi?
Grazie dell'aiuto!:D

andbin
29-06-2007, 16:12
for (int i = 0; i < colonne; i++) {
if (rs.getString(i + 1).equals("true") || rs.getString(i + 1).equals("false")) {
record.add(rs.getBoolean(i + 1));
} else {
record.add(rs.getString(i + 1));
}
}

Che ne pensi?No, non mi sembra una buona cosa. Se vai a vedere la documentazione di getBoolean(), dice:
If the designated column has a datatype of CHAR or VARCHAR and contains a "0" or has a datatype of BIT, TINYINT, SMALLINT, INTEGER or BIGINT and contains a 0, a value of false is returned. If the designated column has a datatype of CHAR or VARCHAR and contains a "1" or has a datatype of BIT, TINYINT, SMALLINT, INTEGER or BIGINT and contains a 1, a value of true is returned.

DigitalKiller
29-06-2007, 16:57
No, non mi sembra una buona cosa. Se vai a vedere la documentazione di getBoolean(), dice:
If the designated column has a datatype of CHAR or VARCHAR and contains a "0" or has a datatype of BIT, TINYINT, SMALLINT, INTEGER or BIGINT and contains a 0, a value of false is returned. If the designated column has a datatype of CHAR or VARCHAR and contains a "1" or has a datatype of BIT, TINYINT, SMALLINT, INTEGER or BIGINT and contains a 1, a value of true is returned.

In origine, la colonna ABILITATO nel database era TINYINT (BOOLEAN in mysql). Sono passato a VARCHAR proprio per visualizzare la checkbox nella jtable. A questo punto posso ritornare anche a TINTINT lasciando inalterato il codice, o no?

andbin
29-06-2007, 17:04
In origine, la colonna ABILITATO nel database era TINYINT (BOOLEAN in mysql). Sono passato a VARCHAR proprio per visualizzare la checkbox nella jtable. A questo punto posso ritornare anche a TINTINT lasciando inalterato il codice, o no?Rimetti pure il campo a BOOLEAN (o TINYINT(1) che poi è la stessa cosa) ma poi nel codice ovviamente non devi usare getString() per quella colonna!

DigitalKiller
29-06-2007, 20:05
Rimetti pure il campo a BOOLEAN (o TINYINT(1) che poi è la stessa cosa) ma poi nel codice ovviamente non devi usare getString() per quella colonna!
No? Io pensavo di fare in questo modo:
for (int i = 0; i < colonne; i++) {
if (rs.getString(i + 1).equals("1") || rs.getString(i + 1).equals("0")) {
record.add(rs.getBoolean(i + 1));
} else {
record.add(rs.getString(i + 1));
}
}
altrimenti sono costretto a fare riferimento al numero di colonna della tabella UTENTI. Il mio intento, invece, è di creare una classe generica per la gestione del database. Ho sbagliato approccio? Mi consigli di fare in qualche altro modo?:)