2010-02-04 12 views
0

J'ai mis en place un modèle de tableau personnalisé comme suit:Exception dans l'implémentation de AbstractTableModel dans JAVA?

public class MyTableModel extends AbstractTableModel { 
    ... 
    ... 
    @Override 
    public Class getColumnClass(int c) { 
     return getValueAt(0, c).getClass(); 
    } 
    ... 
    ... 
} 

Je reçois NullPointerException jeté par la méthode ci-dessus, quand j'afficher un JTable ayant la TableModel ci-dessus.

Je pense que l'exception est due à certaines cellules vides dans la table de base de données.

Si l'exception est due à des cellules vides dans la table de base de données, alors comment se déplacer avec ce problème?

Il n'est pas obligatoire que chaque colonne de la base de données ait une certaine valeur. Certaines colonnes ne peuvent contenir rien.

+2

Je vois que vous n'avez toujours pas regardé le code que je vous ai donné hier lorsque vous avez posé votre question connexe. Les deux solutions ont résolu ce problème. C'est extrêmement ennuyeux de perdre du temps en ne lisant pas toutes les suggestions qui vous ont été faites dans les publications précédentes. – camickr

Répondre

1

Si les cellules peuvent contenir des valeurs vides, l'appel de getClass() sur une valeur nulle vous donnera certainement le NPE. Bien sûr, vous pouvez vérifier null, mais votre vrai problème est plus subtil que cela.

L'interface TableModel spécifie que getColumnClass(int) doit retourner "la superclasse la plus spécifique pour toutes les valeurs de cellule dans la colonne." De l'apparence des choses, vous pourriez retourner n'importe quel nombre de types de classe pour une seule colonne, rompant ainsi le contrat TableModel.

Généralement, les types de colonne sont statiques pour un ensemble donné de données de table, ce qui signifie que la classe d'une colonne ne doit pas changer à moins que les données de la table sous-jacente aient changé. Je pense qu'il est important de se demander pourquoi vous devez retourner une valeur si spécifique.

Dans le cas où vous souhaitez rendre quelque chose de spécifique pour un type de classe donné, il est préférable de lancer le vôtre TableCellRenderer et de déterminer le type d'objet par cellule. De là, vous pouvez faire un rendu spécifique au besoin.

0

Peut-être:

public Class getColumnClass(int c) { 
     return (getValueAt(0, c) == null ? Object.class : getValue(0, c).getClass()); 
    } 

J'espère que cela vous aide.

1

Un problème est que vous obtenez une valeur nulle pour ces coordonnées spécifiques. Si il est légitime et que vous voulez, rien de spécial à rendre, alors ce que vous devez faire est de nul-Check et Object.class par exemple ,:

public Class getColumnClass(int c) { 
     Object o = getValueAt(0, c); 
     if(o==null) return Object.class; 
     return o.getClass() 
    } 

Cela garantira que le moteur de rendu par défaut est utilisé, et puisqu'il n'y a pas de valeur, rien ne sera rendu.

0

En plus des réponses à ce jour: En supposant que votre modèle est soutenu par un List (comme suggéré dans votre question précédente), vous verrez un IndexOutOfBoundsException si essayant de rendre votre JTable lorsque le TableModel ne contient pas de lignes (la List est vide). Ceci est un cas de bord méchant (comme je me rends compte que vous essayez de rendre un ResultSet - Comment savez-vous le ResultSet ne sera pas vide?).

Pour éviter cela, pourquoi n'avez-vous pas fait ce que je vous avais suggéré à l'origine et déterminé la classe de chaque colonne du ResultSetMetaData?

+0

Encore une fois ce problème est traité dans mes deux suggestions qui fournissent un code de travail complet. Parfois je me demande pourquoi je m'embête à poster un code de travail. – camickr

+0

@camickr: J'ai vérifié l'exemple que vous avez posté et vous n'utilisez pas le ResultSetMetaData pour déterminer la classe de colonne; vous le déterminez dynamiquement en itérant sur les données ... à moins que je ne manque quelque chose? – Adamski

+0

J'ai donné deux solutions. Une solution simple qui utilise le DefaultTableModel existant et ne nécessite pas de modèle personnalisé. Le code gère les cellules nulles et vide un modèle. Cette approche économise la création d'un modèle personnalisé. La deuxième solution est plus complexe car elle nécessite l'utilisation d'un modèle personnalisé "générique" pouvant être utilisé dans de nombreuses situations différentes. Dans ce cas, j'ai ensuite inclus une méthode statique pour remplir le modèle à partir d'un ResultSet. Dans ce cas, les métadonnées sont utilisées pour déterminer la classe de colonne. Les deux solutions offrent la possibilité d'ajouter/de supprimer/modifier dynamiquement le modèle. – camickr

0

ResultSetMetaData ne fournit aucune information sur la classe. Il fournit des types de données spécifiques à la base de données qui ne correspondent pas automatiquement aux classes Java (par ex., "cidr" ou "int8" dans le monde de PostgreSQL) donc cette suggestion (qui n'incluait aucun code source, d'ailleurs) n'est pas réellement utile. En outre, le commentaire "Je pense qu'il est important de demander pourquoi vous avez besoin de renvoyer une telle valeur spécifique" par Jason Nichols montre une absence de compréhension générale sur la façon dont la classe JTable est utilisée dans le monde réel.

Je voudrais trouver une solution à ce problème où les tables ont zéro rangées, où je peux encore trouver quelle classe Java je devrais employer pour rendre mes cellules pour la colonne entière. L'idée que la sortie peut changer est basée encore moins sur les bases de données - un type de données de colonne est spécifié dans la définition de cette colonne, et quel que soit son contenu, le type de données ne change pas selon la ligne re le regarder. Bien sûr, l'un des problèmes avec les bases de données est que les définitions de colonnes peuvent ou non autoriser les valeurs NULL, et quiconque sous-classant JTable pour cela devrait comprendre cette prémisse très basique et savoir comment tester cela.