0

I come before you to ask about a problem i have encounter while programming in java. THis topic is about JTable.

Now let's talk about my goal. I have a list of criterion (an arraylist), and a list a scenario (still an arraylist). I have created a class to associate every scenario with a value, and each criterion have a list of this new object (now i will call the new object "ValueCriterion"). A criterion can be a father of 1 or more criterion. I have a tableModel for children (which show each scenario whith the value of this criterion whith the help of ValueCriterion (this model work perfectly) and for parent (which show for each scenario the value of each children; it's this one which don't work).

Now the problem. When i created my 2 criterion (1 is the children of the other), there no problem, i had the scenario, still no problem, but if i had an children to the actual father, when i select the father the program give me an beautiful error (see below). And honestly i don't know what to do anymore to find this bullshit error.

So i hope someone can help me, here the error and the code of the model that didn't work.

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.JTable.prepareRenderer(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paintCell(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paintCells(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paint(Unknown Source)
at javax.swing.plaf.ComponentUI.update(Unknown Source)
at javax.swing.JComponent.paintComponent(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JViewport.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JSplitPane.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JSplitPane.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JSplitPane.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JLayeredPane.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
at java.awt.Container.paint(Unknown Source)
at java.awt.Window.paint(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.access$1300(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

And the code :

package views;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.table.AbstractTableModel;
import models.Controller;
import models.Criterion;
import models.Scenario;
public class TableMod extends AbstractTableModel{

private static final long serialVersionUID = 1L;
private Object[][] data;
private String[] title;
private boolean onEdit = true;
private Criterion criterion;
private Controller cont;

public TableMod(Object[][] data, String[] title) {
    this.data = data;
    this.title = title;
}

public TableMod(Controller c) {
    if(c != null){
        this.criterion = c.getSelectedNode();
        this.cont = c;
        this.title = new String[]{"Scénario"};
        if(criterion!=null){
            this.data = new Object[0][criterion.getChildren().size()+1];
        }else{
            this.data = new Object[0][2];
        }
    }else{
        this.title = new String[]{"Scénario","Childrens"};
        this.data = new Object[0][2];
    }
}

@Override
public int getColumnCount() {
    return this.title.length;
}

@Override
public int getRowCount() {
    return this.data.length;
}

@Override
public Object getValueAt(int row, int col) {
    if(data.length>row){
        if(data[row].length>col){
            return this.data[row][col];
        }else{
            return null;
        }
    }else{
        return null;
    }
}

public Object[][] getValue() {
    return this.data;
}

@Override
public String getColumnName(int col) {
    return this.title[col];
}

@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Class getColumnClass(int col){
    if(data[0].length>col){
        if(data[0][col]!=null){
            if(data[0][col].getClass()!=null){
                return data[0][col].getClass();
            }else{
                return null;
            }
        }else{
            return null;
        }
    }else{
        return null;
    }
}

@Override
public boolean isCellEditable(int row, int col) {
    return (col == 3 && !onEdit)?false:true;
}

@Override
public void setValueAt(Object obj, int row, int col) {
    if((col == 0 || col == 3) && obj.toString().isEmpty())
        return;
    else if(col == 0 && exist(obj, row))
        return;

    this.data[row][col] = obj;
    fireTableCellUpdated(row, col);
}

public void setData(Object[][] data) {
    this.data = data;
    this.fireTableDataChanged();
}

public void setData(String scale){
    for(int i=0; i<data.length; i++)
        this.data[i][3] = scale;
    this.fireTableDataChanged();
}

public void setData(HashMap<String, String> values){
    for(int i=0; i<data.length; i++){
        if(values.containsKey(data[i][0]))
            data[i][3] = values.get(data[i][0]);
    }
    this.fireTableDataChanged();
}

public HashMap<String, String> getValues(){
    HashMap<String, String> map = new HashMap<String, String>();
    for(int i=0; i<data.length; i++){
        map.put(data[i][0].toString(), data[i][3].toString());
    }
    return map;
}

public void load(ArrayList<Scenario> list){
    if(this.criterion!=null){
        if(criterion.getChildren()!=null){
            data = new Object[list.size()][criterion.getChildren().size()+1];
            for(int i=0; i<list.size(); i++){
                data[i][0] = list.get(i).getName();
            }
            this.fireTableDataChanged();
        }
    }
}

public ArrayList<Scenario> getScenarios(){
    int tmp;
    ArrayList<Scenario> list = new ArrayList<Scenario>();
    int t = 0;
    for(int i=0; i<data.length; i++){
        tmp=Scenario.getCount();
        t = i;
        t+= 1;
        Scenario s = new Scenario(data[i][0].toString(),data[i][0].toString(),"",t);
        list.add(s);
        Scenario.setCount(tmp);
    }
    return list;
}

public void addRow(Object[] data){
    int indice = 0;
    int nbRow = this.getRowCount();
    int nbCol = this.getColumnCount();

    Object temp[][] = this.data;
    this.data = new Object[nbRow+1][nbCol];

    for(Object[] value : temp)
        this.data[indice++] = value;

    this.data[indice] = data;
    this.fireTableDataChanged();
}

public void removeRow(int index){
    if(index < 0){
        return;
    }
    int i = 0, j= 0;
    Object temp[][] = new Object[this.getRowCount()-1][this.getColumnCount()];
    for(Object[] value : this.data){
        if(i != index)
            temp[j++] = value;
        i++;
    }
    this.data = temp;
    this.fireTableDataChanged();
}

public void setOnEdit(boolean b){
    onEdit = b;
}

/**
 * Cette méthode teste l'existence d'un objet dans le modèle
 * @param ob objet
 * @param row ligne de l'objet en cours de modification
 * @return vrai en cas de doublon, faux sinon
 */
private boolean exist(Object ob, int row){
    for(int i=0; i<data.length; i++){
        if(i != row && data[i][0].equals(ob)){
            return true;
        }
    }
    return false;
}

public void setTit(Controller c){
    this.criterion=c.getSelectedNode();
    String[] childrenNames = new String[c.getSelectedNode().getChildren().size()+1];
    childrenNames[0]="Scenario";
    for(int i = 0; i<c.getSelectedNode().getChildren().size(); i++){
        childrenNames[i+1]=c.getSelectedNode().getChildren().get(i).getName();
    }
    this.title = childrenNames;
}

public Criterion getCriterion(){
    return this.criterion;
}

public void refreshTable(){
    Object temp[][] = this.data;
    this.data = new Object[this.getRowCount()][this.getColumnCount()];
    for(int i = 0; i<this.getRowCount(); i++){
        this.data[i][0]=temp[i][0];
        for(int j = 1; j<this.getColumnCount(); j++){
            for(int k = 0;k<criterion.getChildren().get(j-1).getCritValue().size();k++){
                if(criterion.getChildren().get(j-1).getCritValue().get(k).getScenarioName().equals(this.data[i][0])){
                    this.data[i][j]=criterion.getChildren().get(j-1).getCritValue().get(k).getValue();
                }
            }
        }
    }
}
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 1
    Possible duplicate of [What is a NullPointerException, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – SomeJavaGuy Jul 07 '16 at 11:18
  • I know what is a nullPointerException, the problem is i can't find where it happen, the only thing i have found is : "Without the line "this.title = childrenNames;" the problem is solve, but the visible table is, well, there just one column isteed of 2-x". But i'll look how he use stack trace. Thx for the help btw – Philippe Alexandre Mars Jul 07 '16 at 11:30
  • To answer your question, that, in some point, the same base problem, but the reolution isn't the same, cause in my code, i don't see where there could be a null. If you look the stack trace, the error come from somewhere else. – Philippe Alexandre Mars Jul 07 '16 at 11:34
  • 2
    It looks, that you've installed renderer, which is null. Unfortunately, the code, you've posted has nothing about the renderer. To get a better help you need to provide a [SSCCE](http://sscce.org). – Sergiy Medvynskyy Jul 07 '16 at 11:37
  • I would love to give you that, the problem is, i don't owed the code. But i can garantee we don't touch the renderer on our application. The code i gave contain all the method we use to modify our tablemodel, and the table itself is just Table thing = new TableMod(this) (it's called in the controller that why the this). – Philippe Alexandre Mars Jul 07 '16 at 11:45
  • 2
    *"I would love to give you that, the problem is, i don't owed the code."* I would love to give you a solution, the problem is, we'd need a [mcve]. Much like an SSCCE as mentioned by @SergiyMedvynskyy, except that we have two close reasons that explicitly mention the MCVE. I chose one, and this question only needs 3 more close votes.. Time to load the code up in the debugger of an IDE and check that what you expect is happening, is actually happening, and if not, why. – Andrew Thompson Jul 07 '16 at 11:52

1 Answers1

3

This worries the heck out of me:

public Class getColumnClass(int col){
    if(data[0].length>col){
        if(data[0][col]!=null){
            if(data[0][col].getClass()!=null){
                return data[0][col].getClass();
            }else{
                return null;
            }
        }else{
            return null;
        }
    }else{
        return null;
    }
}

All those return null; statements don't look healthy and in fact look risky, in particular when the renderer tries to render a cell that holds a null value. At least return super.getColumnClass(col); as your default return statement.

Also, couldn't that method be simplified? For example if a cell holds a non-null value, you know that the value's getClass() won't be null. For example:

public Class getColumnClass(int col) {
    if(data[0].length > col && data[0][col] != null) {
        return data[0][col].getClass();
    } else {
        return super.getColumnClass(col); // a non-null default value
    }
}    

Or perhaps better:

public Class getColumnClass(int col) {
    if (col < 0 || col >= getColumnCount()) {
        String text = "col value: " + col;
        throw new IllegalArgumentException(text);
    } else if(getRowCount() > 0 && data[0][col] != null) {
        return data[0][col].getClass();
    } else {
        return super.getColumnClass(col);
    }
}    
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373