Java 具有非均匀对象数组的JTable,返回自定义TableCellRenderer实现

Java 具有非均匀对象数组的JTable,返回自定义TableCellRenderer实现,java,swing,nullpointerexception,tablecellrenderer,Java,Swing,Nullpointerexception,Tablecellrenderer,我有从JPanel扩展的自定义组件。 名称为:PanelButton和PanelSlider 问题1: 创建xxxTableModel是否有效或安全。。。非均匀矩阵 这相当于3行不同长度的数据: jtblGeneral.setModel(new DefaultTableModel( new Object [][] { {"Cell Row:0,Col:0"}, {"Cell Row:1,Col:0", "Cell Row:1,Col:1"}, {"Cell Row:2,Col:0", "Ce

我有从JPanel扩展的自定义组件。 名称为:PanelButton和PanelSlider

问题1:

创建xxxTableModel是否有效或安全。。。非均匀矩阵

这相当于3行不同长度的数据:

jtblGeneral.setModel(new DefaultTableModel(
  new Object [][] { {"Cell Row:0,Col:0"}, {"Cell Row:1,Col:0", "Cell Row:1,Col:1"}, {"Cell Row:2,Col:0", "Cell Row:2,Col:1"}
  },
  new String [] {
    "Title 1", "Title 2"
  }
));
现在我正在实现自己的TableCellRenderer

问题2:

如果问题的答案是肯定的。当该值为null且未像自定义JPanel类中的行0、列1中的单元格那样定义时,必须返回什么类型的对象

返回null;当我返回null时,我会对Nimbus和GTK的外观和感觉产生问题 UIManager.setLookAndFeeljavax.swing.plaf.nimbus.NimbusLookAndFeel;或 UIManager.setLookAndFeelcom.sun.java.swing.plaf.gtk.GTKLookAndFeel; 以下是异常java.lang.NullPointerException:

  Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at javax.swing.plaf.synth.SynthTableUI.paintCell(SynthTableUI.java:684)
    at javax.swing.plaf.synth.SynthTableUI.paintCells(SynthTableUI.java:580)
    at javax.swing.plaf.synth.SynthTableUI.paint(SynthTableUI.java:364)
    at javax.swing.plaf.synth.SynthTableUI.update(SynthTableUI.java:275)
    at javax.swing.JComponent.paintComponent(JComponent.java:780)
    at javax.swing.JComponent.paint(JComponent.java:1056)
返回新的JLabel; 返回新组件; 问题3:

但是,当值不为null且我不知道类类型时,如何处理返回

如果值!=返回组件值为空; return table.getDefaultRenderString.class.getTableCellRenderComponentTable,value,isSelected,hasFocus,row,column; 扩展组件的MyTableCellRenderer类并返回该类; 所有代码

在异常引发的主方法上建立nimbus LookAndFeel作为第一个操作:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
  at javax.swing.plaf.synth.SynthTableUI.paintCell(SynthTableUI.java:684)
  at javax.swing.plaf.synth.SynthTableUI.paintCells(SynthTableUI.java:580)
  at javax.swing.plaf.synth.SynthTableUI.paint(SynthTableUI.java:364)
  at javax.swing.plaf.synth.SynthTableUI.update(SynthTableUI.java:275)
  at javax.swing.JComponent.paintComponent(JComponent.java:780)
  at javax.swing.JComponent.paint(JComponent.java:1056)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paint(JComponent.java:1065)
  at javax.swing.JViewport.paint(JViewport.java:728)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paint(JComponent.java:1065)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paint(JComponent.java:1065)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paint(JComponent.java:1065)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paint(JComponent.java:1065)
  at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217)
  at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
  at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
  at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
  at javax.swing.JComponent.paint(JComponent.java:1042)
  at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
  at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79)
  at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116)
  at java.awt.Container.paint(Container.java:1975)
  at java.awt.Window.paint(Window.java:3904)
  at javax.swing.RepaintManager$4.run(RepaintManager.java:842)
  at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
  at java.security.AccessController.doPrivileged(Native Method)
  at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
  at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
  at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
  at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
  at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
  at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
  at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
  at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
  at java.awt.EventQueue.access$500(EventQueue.java:97)
  at java.awt.EventQueue$3.run(EventQueue.java:709)
  at java.awt.EventQueue$3.run(EventQueue.java:703)
  at java.security.AccessController.doPrivileged(Native Method)
  at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
  at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
  at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
  at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
  at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
  at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
  at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
  at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
创建xxxTableModel是否有效或安全。。。非均匀矩阵

是的,您可以这样做,但这需要您付出大量的努力才能使其正常工作,因为JTable的设计并不是这样的

如果问题的答案是肯定的。当该值为null且未像自定义JPanel类中的行0、列1中的单元格那样定义时,必须返回什么类型的对象

必须返回组件的实例,不能返回null

但是,当值不为null且我不知道类类型时,如何处理返回

这与第二个问题的答案相同,您必须返回组件的实例,如何处理空值和未知值之间的差异取决于您

观察 在深入研究代码之后,您正在调用updateUI,这是不合适的,这不是在您更改UI状态时触发UI更新的方法,它只用于系统通知组件Look and Feel委托已更改

在TableModel中,您应该在更新模型时触发适当的事件,这将通知父JTable,它将进行适当的更改

我删除了代码中对updateUI的所有调用,只更新了addRow方法以调用fireTableRowsInserted


NullPointerException消失了。您还必须对removeRow进行适当的更改

1。对2.null可以,但是,需要将TableCellRenderer配置为支持null值;3.好的,这取决于您,这是您的规则,在一天结束时,您必须返回ComponentDon't all updateUI的实例,除非您打算更改外观委托,它不是配置表的合适方法不是特别有效TupDateUI处理应用新外观时所需的更改,它不是配置表属性的最佳位置,您应该在创建JTable之后,或者通过创建自定义JTable并重写其构造函数来执行此操作-我正在运行时更改LookAndFeel-尽管已经演示过,但在运行时并不打算更改外观,这是一个副作用,它主要起作用-很抱歉,这应该是不要调用updateUI覆盖updateUI,因为当我更改LookAndFeel时,表没有采用新应用的LookAndFeel。我不知道另一种方法。我知道的大多数改变外观的应用程序都会进行自我终止和更新过程,因为在运行时尝试重新启动会产生奇怪的副作用。我正在阅读这个答案,然后选择返回方法。
  Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at javax.swing.plaf.synth.SynthTableUI.paintCell(SynthTableUI.java:684)
    at javax.swing.plaf.synth.SynthTableUI.paintCells(SynthTableUI.java:580)
    at javax.swing.plaf.synth.SynthTableUI.paint(SynthTableUI.java:364)
    at javax.swing.plaf.synth.SynthTableUI.update(SynthTableUI.java:275)
    at javax.swing.JComponent.paintComponent(JComponent.java:780)
    at javax.swing.JComponent.paint(JComponent.java:1056)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableButtonSlider extends JFrame {

  public TableButtonSlider()  {
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    setSize(600, 300);
    setVisible(true);
    setLocationRelativeTo(null);
  }
  public static void setLAF(Container container, String laf) {
    try {
      UIManager.setLookAndFeel(laf);
    } catch (ClassNotFoundException | InstantiationException
        | IllegalAccessException | UnsupportedLookAndFeelException e) {
    }
    SwingUtilities.updateComponentTreeUI(container);
  }
  static final JFrame frame = new JFrame();
  public JComponent makeUI() {

    String[] hdrsObjects = {"PanelButton Class", "PanelSlider Class"};
    Object[][] objectMatrix = new Object[3][2];
    objectMatrix[0][0] = new PanelButtonData(true);
    objectMatrix[1][0] = new PanelButtonData(false);
    objectMatrix[2][0] = new PanelButtonData(false);

//    objectMatrix[0][1] = new PanelSliderData(10, 30, 40);
    objectMatrix[1][1] = new PanelSliderData(0, 20, 40);
    objectMatrix[2][1] = new PanelSliderData(30, 40, 60);

    JTable Mytable = new JTable(new MyTableModel(objectMatrix, hdrsObjects)) {
      @Override public void updateUI() {
        super.updateUI();
        setRowHeight(30);
        TableColumn tc;

        tc = getColumn("PanelSlider Class");
        tc.setCellRenderer(new MyTableCellRenderer());
        tc.setCellEditor(new MyTableCellEditor());
        tc = getColumn("PanelButton Class");
        tc.setCellRenderer(new MyTableCellRenderer());
        tc.setCellEditor(new MyTableCellEditor());
      }
    };

    JScrollPane scrollPane = new JScrollPane(Mytable);

    JPanel pH = new JPanel();
    pH.setLayout(new BoxLayout(pH, BoxLayout.LINE_AXIS));

    JPanel pV = new JPanel();
    pV.setLayout(new BoxLayout(pV, BoxLayout.PAGE_AXIS));

    JButton bInsert = new JButton("Insert");
    bInsert.addActionListener((ActionEvent e) -> {
      ((MyTableModel)Mytable.getModel()).addRow(
        new Object[] {
          new PanelButtonData(false),
          new PanelSliderData(0, 25, 50)
        }
      );
      Mytable.updateUI();
    });

    JButton bMetal = new JButton("Metal");
    bMetal.addActionListener((ActionEvent) -> {
      setLAF(TableButtonSlider.this, "javax.swing.plaf.metal.MetalLookAndFeel");
    });

    JButton bMotif = new JButton("Motif");
    bMotif.addActionListener((ActionEvent) -> {
      setLAF(TableButtonSlider.this, "com.sun.java.swing.plaf.motif.MotifLookAndFeel");
    });

    JButton bNimbus = new JButton("Nimbus");
    bNimbus.addActionListener((ActionEvent) -> {
      setLAF(TableButtonSlider.this, "javax.swing.plaf.nimbus.NimbusLookAndFeel");
    });

    JButton bMacOS = new JButton("mac");
    bMacOS.addActionListener((ActionEvent evt) -> {
      setLAF(TableButtonSlider.this, "com.apple.laf.AquaLookAndFeel");
    });

    JButton bWindows = new JButton("win");
    bWindows.addActionListener((ActionEvent) -> {
      setLAF(TableButtonSlider.this, "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    });

    JButton bLinux = new JButton("lnx");
    bLinux.addActionListener((ActionEvent) -> {
      setLAF(TableButtonSlider.this, "com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
    });

    pH.add(bInsert);
    pH.add(Box.createRigidArea(new Dimension(1,0)));
    pH.add(new JSeparator(JSeparator.VERTICAL));
    pH.add(Box.createRigidArea(new Dimension(1,0)));
    pH.add(bLinux);
    pH.add(bMacOS);
    pH.add(bWindows);
    pH.add(Box.createRigidArea(new Dimension(1,0)));
    pH.add(new JSeparator(JSeparator.VERTICAL));
    pH.add(Box.createRigidArea(new Dimension(1,0)));
    pH.add(bMetal);
    pH.add(bMotif);
    pH.add(bNimbus);

    pV.add(pH);
    pV.add(scrollPane);
    return pV;
  }
  public static void main(String... args) {
    UIManager.put("Slider.paintValue", false);
    EventQueue.invokeLater(() -> {
      TableButtonSlider f = new TableButtonSlider();
      f.getContentPane().add(f.makeUI());
    });
  }
}

class PanelButton extends JPanel {
  JButton jbtWavRow = new JButton();
  private final JPanel panel = new JPanel();
  PanelButton(PanelButtonData data) {
    super();
    panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
    panel.add(Box.createRigidArea(new Dimension(2,0)));
    panel.add(jbtWavRow);
    panel.add(Box.createRigidArea(new Dimension(2,0)));
    jbtWavRow.setFont(new Font("Monospaced", Font.PLAIN, 10));
    setData(data);
    setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
    add(panel);
  }
  public PanelButtonData getData() {
    return new PanelButtonData(jbtWavRow.getActionCommand().equals("+"));
  }
  public void setData(PanelButtonData data) {
    for (ActionListener al : jbtWavRow.getActionListeners()) {
      jbtWavRow.removeActionListener(al);
    }

    if(data.getIns()) {
      jbtWavRow.setText("Insert");
      jbtWavRow.setActionCommand("+");
      jbtWavRow.addActionListener((ActionEvent e) -> {
        JTable table = (JTable)SwingUtilities.getAncestorOfClass(
            JTable.class, (Component) e.getSource());
        table.getCellEditor().stopCellEditing();
        ((MyTableModel)table.getModel()).addRow(
            new Object[] {
              new PanelButtonData(false),
              new PanelSliderData(0, 25, 50)
            }
        );
        table.updateUI();
      });
    } else {
      jbtWavRow.setText("Remove");
      jbtWavRow.setActionCommand("-");
      jbtWavRow.addActionListener((ActionEvent e) -> {
        JTable table = (JTable) SwingUtilities.getAncestorOfClass(
            JTable.class, (Component) e.getSource());

        int row = table.getEditingRow();
        table.getCellEditor().stopCellEditing();
        ((MyTableModel) table.getModel()).removeRow(row);
        // table.updateUI();
      });
    }
  }
}

class PanelButtonData {
  private boolean add = false;
  PanelButtonData(Boolean add) { this.add = add; }
  public void setIns(Boolean add) { this.add = add; }
  public boolean getIns() { return add; }
}

class PanelSlider extends JPanel {
  private final JSlider jslChanger = new JSlider(SwingConstants.HORIZONTAL);
  private final JPanel panel = new JPanel();
  PanelSlider(PanelSliderData data) {
    super();
    panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
    panel.add(Box.createRigidArea(new Dimension(2,0)));
    panel.add(jslChanger);
    panel.add(Box.createRigidArea(new Dimension(2,0)));
    setData(data);
    setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
    add(panel);
  }
  public void setData(PanelSliderData data) {
    jslChanger.setMinimum(data.getMin());
    jslChanger.setValue(data.getVal());
    jslChanger.setMaximum(data.getMax());
  }
  // Used in MyTableCellRenderer.getCellEditorValue()
  public PanelSliderData getData() {
    return new PanelSliderData(jslChanger.getMinimum(), jslChanger.getValue(), jslChanger.getMaximum());
  }
}

class PanelSliderData {
  private Integer Min = 0;
  private Integer Val = 25;
  private Integer Max = 50;
  PanelSliderData(int Min, int Val, int Max) {
    this.Min = Min;
    this.Val = Val;
    this.Max = Max;
  }
  public Integer getMin() { return Min; }
  public Integer getVal() { return Val; }
  public Integer getMax() { return Max; }
}

class MyTableCellRenderer implements TableCellRenderer {
  private final PanelSlider ps = new PanelSlider(new PanelSliderData(0, 25, 50));
  private final PanelButton pb = new PanelButton(new PanelButtonData(false));
  @Override public Component getTableCellRendererComponent(
      JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    if (value instanceof PanelButtonData) {
      pb.setData((PanelButtonData) value);
      return pb;
    }
    if (value instanceof PanelSliderData) {
      ps.setData((PanelSliderData) value);
      return ps;
    }

    //if (value != null)
    //  return (Component) value;
    //return this;

    return null;

    //return table.getDefaultRenderer(String.class).getTableCellRendererComponent(
    //    table, value, isSelected, hasFocus, row, column);

    //return new JLabel();
  }
}

class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor {
  protected Object output;
  private final PanelButton pb = new PanelButton(new PanelButtonData(false));
  private final PanelSlider ps = new PanelSlider(new PanelSliderData(0, 25, 50));
  @Override public Object getCellEditorValue() {
    if (output instanceof PanelButton) {
      return pb.getData();
    }
    if (output instanceof PanelSlider) {
      return ps.getData();
    }
    return null;
  }
  @Override public Component getTableCellEditorComponent(
      JTable table, Object value, boolean isSelected, int row, int column) {
    if (value instanceof PanelButtonData) {
      pb.setData((PanelButtonData) value);
      output = pb;
      return pb;
    }
    if (value instanceof PanelSliderData) {
      ps.setData((PanelSliderData) value);
      output = ps;
      return ps;
    }
    return null;
  }
}

class MyTableModel extends AbstractTableModel {
//class MyTableModel extends DefaultTableModel {
  private Object[][] data;
  private Object[] columns;
  public MyTableModel(Object[][] data, Object[] columns) {
    this.data = data;
    this.columns = columns;
  }
  @Override public Object getValueAt(int rowIndex, int columnIndex) {
    if (data != null) {
      if (data.length > 0) {
        return data[rowIndex][columnIndex];
      }
    }
    return null;
  }
  @Override public int getColumnCount() {
    return ((columns == null) ? 0: columns.length);
  }
  @Override public int getRowCount() {
    return ((data == null) ? 0: data.length);
  }
  @Override public Class getColumnClass(int columnIndex) {
    if (data != null) {
      if (data.length > 0) {
        if (data[0][columnIndex] instanceof PanelButton) {
          return PanelButton.class;
        }
        if (data[0][columnIndex] instanceof PanelSlider) {
          return PanelSlider.class;
        }
        //return data[0][columnIndex].getClass();
        return String.class;
      }
    }
    return Object.class;
  }
  @Override public boolean isCellEditable(int rowIndex, int columnIndex) {
    return true;
  }
  @Override public void setValueAt(Object value, int row, int col) {
    data[row][col] = value;
    fireTableCellUpdated(row, col);
  }
  @Override public String getColumnName(int columnIndex) {
    return (String)columns[columnIndex];
  }
  //@Override 
  public void removeRow(int row) {
    Object[][] newData = new Object[data.length - 1][data[0].length];
    int rown = 0;
    for (int row1 = 0; row1 <data.length; row1++) {
      if (row1 != row) {
        for (int col = 0; col < data[0].length; col++) {
          newData[rown][col] = data[row1][col];
        }
        rown++;
      }
    }
    data = newData;
  }
  //@Override 
  public void addRow(Object[] rowData) {
    Object[][] newData;
    int maxCol;
    if ((data != null) && (data.length > 0)) {
      newData = new Object[data.length + 1][data[0].length];
      for (int row = 0; row <data.length; row++) {
        for (int col = 0; col < data[0].length; col++) {
          newData[row][col] = data[row][col];
        }
      }
      maxCol = data[0].length < rowData.length?data[0].length:rowData.length;
    } else {
      newData = new Object[1][rowData.length];
      maxCol = rowData.length;
    }
    //Insert rowData objects
    for (int col = 0; col < maxCol; col++) {
      newData[newData.length - 1][col] = rowData[col];
    }
    data = newData;
  }
}
  public static void main(String... args) {
    UIManager.put("Slider.paintValue", false);
    try {
      UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
    } catch (ClassNotFoundException | InstantiationException
        | IllegalAccessException | UnsupportedLookAndFeelException e) { }

    EventQueue.invokeLater(() -> {
      TableButtonSlider f = new TableButtonSlider();
      f.getContentPane().add(f.makeUI());
    });
  }
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
  at javax.swing.plaf.synth.SynthTableUI.paintCell(SynthTableUI.java:684)
  at javax.swing.plaf.synth.SynthTableUI.paintCells(SynthTableUI.java:580)
  at javax.swing.plaf.synth.SynthTableUI.paint(SynthTableUI.java:364)
  at javax.swing.plaf.synth.SynthTableUI.update(SynthTableUI.java:275)
  at javax.swing.JComponent.paintComponent(JComponent.java:780)
  at javax.swing.JComponent.paint(JComponent.java:1056)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paint(JComponent.java:1065)
  at javax.swing.JViewport.paint(JViewport.java:728)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paint(JComponent.java:1065)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paint(JComponent.java:1065)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paint(JComponent.java:1065)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paint(JComponent.java:1065)
  at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
  at javax.swing.JComponent.paintChildren(JComponent.java:889)
  at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217)
  at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
  at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
  at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
  at javax.swing.JComponent.paint(JComponent.java:1042)
  at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
  at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79)
  at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116)
  at java.awt.Container.paint(Container.java:1975)
  at java.awt.Window.paint(Window.java:3904)
  at javax.swing.RepaintManager$4.run(RepaintManager.java:842)
  at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
  at java.security.AccessController.doPrivileged(Native Method)
  at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
  at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
  at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
  at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
  at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
  at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
  at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
  at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
  at java.awt.EventQueue.access$500(EventQueue.java:97)
  at java.awt.EventQueue$3.run(EventQueue.java:709)
  at java.awt.EventQueue$3.run(EventQueue.java:703)
  at java.security.AccessController.doPrivileged(Native Method)
  at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
  at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
  at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
  at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
  at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
  at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
  at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
  at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
public void addRow(Object[] rowData) {
    Object[][] newData;
    int maxCol;
    if ((data != null) && (data.length > 0)) {
        newData = new Object[data.length + 1][data[0].length];
        for (int row = 0; row < data.length; row++) {
            for (int col = 0; col < data[0].length; col++) {
                newData[row][col] = data[row][col];
            }
        }
        maxCol = data[0].length < rowData.length ? data[0].length : rowData.length;
    } else {
        newData = new Object[1][rowData.length];
        maxCol = rowData.length;
    }
    //Insert rowData objects
    for (int col = 0; col < maxCol; col++) {
        newData[newData.length - 1][col] = rowData[col];
    }
    data = newData;
    fireTableRowsInserted(data.length - 1, data.length - 1);
}