0

I am trying to populate a JTable object, but when the instruction private final DefaultTableModel tarifModel = (DefaultTableModel) tbTarife.getModel(); is called, I am getting a NullPointerException.

I am using Netbeans 8.2 and the GUI Builder plugin to create the JTable.

I've already implemented the part described here and any other question reagarding this problem seems to be not applicable.

My code:

public class TarifDialog extends javax.swing.JPanel {

    private final TarifParser tP;

    public TarifDialog() {

         initComponents();
         tP = new TarifParser(this);

    }

    //Generated code
    private void initComponents() {

        tbTarife = new javax.swing.JTable();
        scrollpTarife = new javax.swing.JScrollPane();

        tbTarife.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Schlüssel", "Name", "Beschreibung", "Preis", "Typ"
            }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false, false, false, false
            };

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        scrollpTarife.setViewportView(tbTarife);
    }

    private javax.swing.JScrollPane scrollpTarife;
    private javax.swing.JTable tbTarife;
    //End generated code

    private final DefaultTableModel tarifModel = (DefaultTableModel) tbTarife.getModel();

    public void addTarifToTable(String Key, String name, String description, double price, String type) {     
        tarifModel.addRow(new Object[]{Key, name, description, price, type});
    }
}

And the class that accesses it:

public final class TarifParser {
    private final TarifVerwaltung tV;
    private final TarifDialog tD;

    public TarifParser(TarifDialog tD) {
        this.tV = Init.getTarifVerwaltung();
        this.tD = tD;
        populateTarifTable();
    }

    public void populateTarifTable() {
        for (HashMap.Entry<String, Tarif> tariff : tV.getAllTariffs().entrySet()) {
            String type = "Undefined";
            if (tariff.getValue().getType() == 0) {
                type = "Standard Tarif";
            } else if (tariff.getValue().getType() == 1) {
                type = "Wiederkehrender Tarif";
            } else if (tariff.getValue().getType() == 2) {
                type = "Einmaliger Tarif";
            }
            tD.addTarifToTable(tariff.getKey(), tariff.getValue().getName(), tariff.getValue().getDescription(), tariff.getValue().getPrice(), type);
        }
    }
}
  • Well, that's a problem of the initializer block running before the constuctor so `(DefaultTableModel) tbTarife.getModel();` runs before `initComponents()` which initializes the table. Why don't you move that part into `initComponents()` as well? – Thomas May 21 '19 at 13:20
  • I cannot access the initComponents(), as any generated code is locked by the GUI Builder plugin. – UmBottesWillen May 21 '19 at 13:23
  • A few side notes: I'd prefer defining fields before methods in order to reduce confusion about the order in which any potential initialization might run and because they're easier to find there (though that's just my opinion). Also `Init.getTarifVerwaltung();` indicates you're using some static globals which in most cases is a design smell so I'd think about whether that's wise (you could pass it to the constructor instead). Also names like `tV` are quite cryptic and can cause confusion and errors in the long run so I'd suggest using somewhat more descriptive names. – Thomas May 21 '19 at 13:25
  • Well, I didn't use gui builders in a long while but IIRC they allow you to add custom code. If they don't then put that line into the constructor to be called there or just use the getter (i.e. make `tarifModel` a virtual property and have the getter directly return `(DefaultTableModel) tbTarife.getModel()`). – Thomas May 21 '19 at 13:27
  • I've moved the entire declaration into the `addTarifToTable(...)` function, and while not ideal, it at least works. – UmBottesWillen May 21 '19 at 13:32
  • 1
    Well, I'm not sure this is that "not ideal". After all you're accessing the table's model which might be changed at some point so having a final variable referencing the _initial_ model might not be ideal in the first place (and getting the model from the table along with a cast costs next to nothing). IMO the only not so ideal part would be that if you'd have another method that needs the model you'd need to duplicate that declaration, hence the suggestion to use the getter and put the conversion there, so `tarifModel.xxx` becomes `getTarifModel().xxx`. – Thomas May 21 '19 at 13:53

0 Answers0