Ошибка в getRowCount() в DefaultTableModel

ИЗМЕНИТЬ

Я попытался изменить модель таблицы обратно на DefaultTableModel, но я получаю исключение при компиляции моего кода, и я не могу понять, почему!

Вот моя таблица инициализации:

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?


person Luis Afonso Teixeira    schedule 19.07.2012    source источник
comment
Почему не setAutoCreateRowSorter(true)?   -  person trashgod    schedule 19.07.2012
comment
лучше подумать, я думаю, что это может быть действительно достаточно!   -  person Luis Afonso Teixeira    schedule 19.07.2012


Ответы (1)


Здесь у вас есть два очевидных выбора: либо дать вашему классу метод getVectorData(), либо дать ему другой столь же полезный метод, который позволит вам извлечь ядро ​​ваших данных из вашей модели. Вероятно, вам не следует использовать переменную AbstractTableModel, а лучше использовать переменную вашего собственного пользовательского типа, которая расширяет AbstractTableModel, чтобы вы могли вызывать пользовательские методы вашей модели.

i.e.,

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

Кроме того, это заявление:

Недавно я создал свой собственный класс для расширения AbstractTableModel, чтобы иметь возможность вставлять некоторую логику в isCellEditable и setValueAt.

Для меня это не имеет смысла, поскольку вы всегда можете использовать DefaultTableModel и просто переопределить эти два метода. Но если вы используете DefaultTableModel, не держите в нем также 2D-массив объектов, как вы пытаетесь это сделать. Скорее подавайте данные в его внутренние данные через соответствующий конструктор или через его метод addRow(...). В противном случае вы потеряете всю мощь, которую может предложить DefaultTableModel.

Редактировать
Если вы хотите использовать DefaultTableModel для усиления своих методов, вы не можете использовать отдельное «ядро» данных для своей модели (здесь ваш 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("--------------------------");
   }
}
person Hovercraft Full Of Eels    schedule 19.07.2012
comment
Я думаю, что в данный момент я делаю беспорядок, мне лучше остановиться и переосмыслить то, что я делаю. И вы правы, причина, по которой я использовал AbstractTableModel, заключалась в том, чтобы иметь возможность добавить ColorEditor к одному из столбцов! Я постараюсь переделать все это с нуля с предложенными вами вариантами и вернусь с результатом. - person Luis Afonso Teixeira; 19.07.2012
comment
Ну, я работал над этим в течение последних 2 или 3 часов, но не могу найти решение. Если я приму AbstractTableModel, я потеряю функции removeRow и moveRow (я пытался создать методы, но получаю некоторые ошибки). Я вернулся к DefaultTableModel, но теперь даже не могу скомпилировать, так как есть проблема с getRowCount() из модели. Я попытаюсь отредактировать свой первоначальный вопрос, если вы можете взглянуть. Еще одна вещь: могу ли я использовать ColorEditor в качестве редактора таблицы при использовании DefaultTableModel? - person Luis Afonso Teixeira; 20.07.2012
comment
Ясно, тогда бессмысленный вопрос! Какой-нибудь намек на проблему getRowCount(), которую я редактировал в своем первоначальном вопросе? Спасибо, что помогли мне. - person Luis Afonso Teixeira; 20.07.2012
comment
Понял! У меня все работает с вашим кодом! Большое спасибо! Я попытаюсь получить его прямо сейчас, используя метод addRow(...) по умолчанию, чтобы убедиться, что я полностью его понял! На данный момент большое спасибо, у меня все работает отлично! :D - person Luis Afonso Teixeira; 20.07.2012