DefaultTableModel上的getRowCount()出错

时间:2012-07-19 03:15:44

标签: java swing jtable abstracttablemodel defaulttablemodel

修改

我已经尝试将表模型更改回DefaultTableModel但是在编译代码时遇到异常,我无法弄清楚原因!

这是我的表init:

jTable1.setModel(new Table1Model());
jTable1.setDefaultRenderer(Color.class,new ColorRenderer(true));
jTable1.getColumnModel().getColumn(5).setCellEditor(new ColorEditor());

我的课程扩展模型:

class Table1Model extends DefaultTableModel {
    //private String[] columnNames = {"Station #",
    private Object[] columnNames = {"Station #",
                                    "Name",
                                    "avg Time",
                                    "Buffer",
                                    "Buffer Parts",
                                    "Color"};
    private Object[][] data = {
    {"1", "Station 1",
     new Integer(10), false, new Integer(0), Color.red},
    {"2", "Station 2",
     new Integer(10), false, new Integer(0), Color.blue},
    {"3", "Station 3",
     new Integer(10), false, new Integer(0), Color.green},
    {"4", "Station 4",
     new Integer(10), false, new Integer(0), Color.orange},
    {"5", "Station 5",
     new Integer(10), false, new Integer(0), Color.black}
    };


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

   @Override
    public int getRowCount() {
       //int length = data.length;
       //int datalength = Integer.parseInt(length);
       return data.length;
    }

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

    @Override
    public Object getValueAt(int row, int col) {
        return data[row][col];
    }

    /*
     * JTable uses this method to determine the default renderer/
     * editor for each cell.  If we didn't implement this method,
     * then the last column would contain text ("true"/"false"),
     * rather than a check box.
     */
    @Override
    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }

    /*
     * Don't need to implement this method unless your table's
     * editable.
     */
    @Override
    public boolean isCellEditable(int row, int col) {
        //Note that the data/cell address is constant,
        //no matter where the cell appears onscreen.
        if (col == 0) { return false; }
        else if (col == 4) { 
            boolean di = (Boolean) getValueAt(row,(col-1));
            if (!di) { return false; }
            else { return true; }
        }
        else { return true; }
    }

    /*
     * Don't need to implement this method unless your table's
     * data can change.
     */
    @Override
    public void setValueAt(Object value, int row, int col) {
        data[row][col] = value;
        fireTableCellUpdated(row, col);
    }

   /*public void removeRow(int row) {
        data.removeRow(row);
    }*/


    private void printDebugData() {
        int numRows = getRowCount();
        int numCols = getColumnCount();

        for (int i=0; i < numRows; i++) {
            System.out.print("    row " + i + ":");
            for (int j=0; j < numCols; j++) {
                System.out.print("  " + data[i][j]);
            }
            System.out.println();
        }
        System.out.println("--------------------------");
    }
}

这会产生以下错误:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at SimGui$Table1Model.getRowCount(SimGui.java:863)
at javax.swing.table.DefaultTableModel.setDataVector(DefaultTableModel.java:224)
at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:124)
at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:106)
at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:86)
at SimGui$Table1Model.<init>(SimGui.java:832)
at SimGui.initComponents(SimGui.java:265)
at SimGui.<init>(SimGui.java:34)
at SimGui$16.run(SimGui.java:789)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:701)
at java.awt.EventQueue.access$000(EventQueue.java:102)
at java.awt.EventQueue$3.run(EventQueue.java:662)
at java.awt.EventQueue$3.run(EventQueue.java:660)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:671)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)
你能帮我弄清楚什么是错的吗? 另外,我可以将ColorEditor与DefaultTableModel一起使用吗?

1 个答案:

答案 0 :(得分:4)

这里有两个明显的选择:要么给你的班级getVectorData()方法,要么给它另一个同样有用的方法,让你从模型中提取数据的核心。您可能不应该使用AbstractTableModel变量,而是使用您自己的自定义类型的变量来扩展AbstractTableModel,以便您能够调用模型的自定义方法。

即,

MyTableModel model = (MyTableModel)jTable1.getModel();
SomeCollection myKeyData = model.getMyKeyData();

另外,这句话:

  

我最近创建了自己的类来扩展AbstractTableModel,以便能够在isCellEditable和setValueAt上插入一些逻辑。

对我来说没有意义,因为你总是可以使用DefaultTableModel并简单地覆盖这两个方法。但是如果你使用DefaultTableModel,也不要让它像你想要的那样持有对象的2D数组。而是通过适当的构造函数或通过其addRow(...)方法将数据提供到其内部数据中。否则,你将失去DefaultTableModel提供的所有功能。

修改
如果你想使用DefaultTableModel来利用它的方法,那么就不能为你的模型使用单独的数据“nucleus”(这里是你的Object [] []),而是必须将你的数据加载到在DefaultTableModel超类内部保存的模型。这可以通过正确的超级构造函数或使用其addRow(...)方法添加数据行来完成。

例如,我在这里将数据加载到DefaultTableModel覆盖:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

import javax.swing.*;
import javax.swing.table.*;

public class TableModelTest extends JPanel {
   private static final Object[][] DATA = {
         { "1", "Station 1", new Integer(10), false, new Integer(0), Color.red },
         { "2", "Station 2", new Integer(10), false, new Integer(0), Color.blue },
         { "3", "Station 3", new Integer(10), false, new Integer(0),
               Color.green },
         { "4", "Station 4", new Integer(10), false, new Integer(0),
               Color.orange },
         { "5", "Station 5", new Integer(10), false, new Integer(0),
               Color.black } };
   private MyTableModel myTableModel = new MyTableModel(DATA);
   private JTable table = new JTable(myTableModel);

   public TableModelTest() {
      setLayout(new BorderLayout());
      add(new JScrollPane(table), BorderLayout.CENTER);

      table.getColumnModel().getColumn(5)
            .setCellRenderer(new ColorCellRenderer());
      table.getColumnModel().getColumn(5).setCellEditor(new ColorCellEditor());
   }

   private static void createAndShowGui() {
      TableModelTest mainPanel = new TableModelTest();

      JFrame frame = new JFrame("TableModelTest");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class ColorCellEditor extends AbstractCellEditor implements TableCellEditor {

   Color currentColor;
   JButton button;
   JColorChooser colorChooser;
   JDialog dialog;
   protected static final String EDIT = "edit";

   public ColorCellEditor() {
      ActionListener actionListener = new MyActionListener();
      button = new JButton();
      button.setActionCommand(EDIT);
      button.addActionListener(actionListener);
      button.setBorderPainted(false);

      colorChooser = new JColorChooser();
      dialog = JColorChooser.createDialog(button, "Pick a Color", true,
            colorChooser, actionListener, null);
   }

   private class MyActionListener implements ActionListener {

      public void actionPerformed(ActionEvent e) {
         if (EDIT.equals(e.getActionCommand())) {
            button.setBackground(currentColor);
            colorChooser.setColor(currentColor);
            dialog.setVisible(true);

            fireEditingStopped();

         } else {
            currentColor = colorChooser.getColor();
         }
      }
   }

   public Object getCellEditorValue() {
      return currentColor;
   }

   public Component getTableCellEditorComponent(JTable table, Object value,
         boolean isSelected, int row, int column) {
      currentColor = (Color) value;
      return button;
   }
}

class ColorCellRenderer implements TableCellRenderer {
   private static final int IMG_WIDTH = 70;
   private static final int IMG_HEIGHT = 20;
   private JLabel label = new JLabel();

   @Override
   public Component getTableCellRendererComponent(JTable table, Object value,
         boolean arg2, boolean arg3, int arg4, int arg5) {
      Color color = (Color) value;
      BufferedImage img = new BufferedImage(IMG_WIDTH, IMG_HEIGHT,
            BufferedImage.TYPE_INT_RGB);
      Graphics g = img.getGraphics();
      g.setColor(color);
      g.fillRect(0, 0, IMG_WIDTH, IMG_HEIGHT);
      g.dispose();
      ImageIcon icon = new ImageIcon(img);
      label.setIcon(icon);
      return label;
   }

}

class MyTableModel extends DefaultTableModel {
   private static final String[] COLUMN_NAMES = { "Station #", "Name",
         "avg Time", "Buffer", "Buffer Parts", "Color" };

   public MyTableModel(Object[][] data) {
      super(data, COLUMN_NAMES);
   }

   @Override
   public boolean isCellEditable(int row, int col) {

      if (col == 0) {
         return false;
      } else if (col == 4) {
         boolean di = (Boolean) getValueAt(row, (col - 1));
         if (!di) {
            return false;
         } else {
            return true;
         }
      } else {
         return true;
      }
   }

   public void printDebugData() {
      int numRows = getRowCount();
      int numCols = getColumnCount();

      for (int i = 0; i < numRows; i++) {
         System.out.print("    row " + i + ":");
         for (int j = 0; j < numCols; j++) {
            Object datum = getValueAt(i, j);
            // System.out.print("  " + data[i][j]);
            System.out.print("  " + datum);
         }
         System.out.println();
      }
      System.out.println("--------------------------");
   }
}