2017-06-06 59 views
0

我做一步一步...添加和刪除行的自定義組件的JTable中

Changing LookAndFeel of JTable of Custom Component

注意我有更多的自定義列,此代碼是用於演示海豚。

現在,我想實現添加行和刪除行使用從DefaultTableModel擴展的類,爲JTable填充自定義對象。

這裏我的代碼:

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.table.*; 

public class LAF_TableCustom_AddDelRow { 

    static JFrame frame = new JFrame(); 

    public JComponent makeUI() { 

    String[] hdrsObjects = {"PanelSpinnerRadioButton Class Column"}; 
    Object[][] objectMatrix = new Object[3][1]; 
    objectMatrix[0][0] = new PanelSpinnerRadioButtonData(false, 10, 40); 
    objectMatrix[1][0] = new PanelSpinnerRadioButtonData(true, 20, 40); 
    objectMatrix[2][0] = new PanelSpinnerRadioButtonData(false, 30, 40); 

// JTable table = new JTable(new DefaultTableModel(objectMatrix, hdrsObjects)) { 
    JTable table = new JTable(new PSRBTableModel(objectMatrix, hdrsObjects)) { 
     @Override public void updateUI() { 
     super.updateUI(); 
     setRowHeight(30); 
     TableColumn tc = getColumn("PanelSpinnerRadioButton Class Column"); 
     tc.setCellRenderer(new PSRBTableCellRenderer()); 
     tc.setCellEditor(new PSRBTableCellEditor()); 
     } 
    }; 

    JScrollPane scrollPane = new JScrollPane(table); 
    scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 
    scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 

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

    JButton bAddRow = new JButton("Add Row"); 
    bAddRow.addActionListener(new ActionListener() { 
     @Override public void actionPerformed(ActionEvent evt) { 
     ((PSRBTableModel)table.getModel()).addRow(
      new Object[] { new PanelSpinnerRadioButtonData(false, 10, 40) } 
     ); 
//  ((DefaultTableModel)table.getModel()).addRow(
//   new Object[] { new PanelSpinnerRadioButtonData(false, 10, 40) } 
//  ); 
     } 
    }); 

    pV.add(bAddRow); 
    pV.add(scrollPane); 
    return pV; 
    } 

    public static void main(String... args) { 
    EventQueue.invokeLater(() -> { 
    frame.getContentPane().add(new LAF_TableCustom_AddDelRow().makeUI()); 
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    frame.setSize(320, 240); 
    frame.setVisible(true); 
    }); 
    } 

} 

class PanelSpinnerRadioButtonData { 
    private boolean opt02 = false; 
    private Integer from = 0; 
    private Integer size = 1; 

    PanelSpinnerRadioButtonData() { 
    this(false, 5, 10); 
    } 
    PanelSpinnerRadioButtonData(boolean opt02, Integer from, Integer size) { 
    this.opt02 = opt02; 
    this.from = from; 
    this.size = size; 
    } 
    public boolean getOption() { 
    return opt02; 
    } 
    public Integer getFrom() { 
    return from; 
    } 
    public Integer getSize() { 
    return size; 
    } 
} 

class PanelSpinnerRadioButton extends JPanel { 
    public final JRadioButton jrbOption01 = new JRadioButton("01"); 
    public final JRadioButton jrbOption02 = new JRadioButton("12"); 
    public final JSpinner jspnValues = new JSpinner(new SpinnerNumberModel(5, 0, 10, 1)); 
    public final JButton jbRemoveRow = new JButton("Del Row"); 

    private final JPanel panel = new JPanel(); 

    PanelSpinnerRadioButton() { 
    this(new PanelSpinnerRadioButtonData(false, 20, 40)); 
    } 
    PanelSpinnerRadioButton(PanelSpinnerRadioButtonData data) { 
    super(); 

    panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS)); 
    panel.add(jrbOption01); 
    panel.add(jrbOption02); 
    panel.add(jspnValues); 
    panel.add(jbRemoveRow); 

    jbRemoveRow.addActionListener(new ActionListener() { 
     @Override public void actionPerformed(ActionEvent e) { 
     JTable table = (JTable)SwingUtilities.getAncestorOfClass(
      JTable.class, (Component) e.getSource()); 
     int row = table.getEditingRow(); 
     table.getCellEditor().stopCellEditing(); 
//  ((DefaultTableModel) table.getModel()).removeRow(row); 
     ((PSRBTableModel) table.getModel()).removeRow(row); 

     } 
    }); 

    ButtonGroup bg = new ButtonGroup(); 
    bg.add(jrbOption01); 
    bg.add(jrbOption02); 
    ((SpinnerNumberModel) jspnValues.getModel()).setMaximum(data.getSize()); 
    setData(data); 

    init(); 
    } 
    private void init() { 
    setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); 
    setBackground(new Color(0, 0, 0, 0)); 
    add(panel); 
    } 
    public void setData(PanelSpinnerRadioButtonData data) { 
    if (data.getOption()) { 
     jrbOption02.setSelected(true); 
    } else { 
     jrbOption01.setSelected(true); 
    } 
    ((SpinnerNumberModel) jspnValues.getModel()).setValue(data.getFrom()); 
    } 
    public PanelSpinnerRadioButtonData getData() { 
    return new PanelSpinnerRadioButtonData(
     jrbOption02.isSelected(), 
     (Integer) ((SpinnerNumberModel) jspnValues.getModel()).getValue(), 
     (Integer) ((SpinnerNumberModel) jspnValues.getModel()).getMaximum()); 
    } 

} 

class PSRBTableCellRenderer implements TableCellRenderer { 
    private final PanelSpinnerRadioButton renderer = new PanelSpinnerRadioButton(); 
    @Override public Component getTableCellRendererComponent(
     JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 
    if (value instanceof PanelSpinnerRadioButtonData) { 
     renderer.setData((PanelSpinnerRadioButtonData) value); 
    } 
    return renderer; 
    } 
} 

class PSRBTableCellEditor extends AbstractCellEditor implements TableCellEditor { 
    private final PanelSpinnerRadioButton editor = new PanelSpinnerRadioButton(); 
    @Override public Object getCellEditorValue() { 
    return editor.getData(); 
    } 
    @Override public Component getTableCellEditorComponent(
     JTable table, Object value, boolean isSelected, int row, int column) { 
    if (value instanceof PanelSpinnerRadioButtonData) { 
     editor.setData((PanelSpinnerRadioButtonData) value); 
    } 
    return editor; 
    } 

} 

//class PSRBTableModel extends AbstractTableModel { 
class PSRBTableModel extends DefaultTableModel { 

    private final Object[][] data; 
    private final Object[] columns; 

    public PSRBTableModel(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 PanelSpinnerRadioButton) { 
      return PanelSpinnerRadioButton.class; 
     } 
     return data[0][columnIndex].getClass(); 
     } 
    } 
    return Object.class; 
    } 

    @Override public boolean isCellEditable(int rowIndex, int columnIndex) { 
    if (data != null) { 
     if (data.length > 0) { 
     if (data[0][columnIndex] instanceof PanelSpinnerRadioButton) { 
      return true; 
     } 
     } 
    } 
    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) { 
    fireTableRowsDeleted(row, row); 
    System.out.println("fireTableRowsDeleted(" + row + ", " + row + ");"); 
    } 

    @Override public void addRow(Object[] rowData) { 
    super.addRow(rowData); 
    } 
} 

的問題!

當我按下Del Row按鈕時,行未被刪除! 我得到了與該行相關的打印信息:fireTableRowsDeleted(ROW, ROW);

當我按下Add Row我得到這個異常...

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3 > 0 
    at java.util.Vector.insertElementAt(Vector.java:598) 
    at javax.swing.table.DefaultTableModel.insertRow(DefaultTableModel.java:374) 
    at javax.swing.table.DefaultTableModel.addRow(DefaultTableModel.java:350) 
    at javax.swing.table.DefaultTableModel.addRow(DefaultTableModel.java:361) 
    at PSRBTableModel.addRow(LAF_TableCustom_AddDelRow.java:248) 
    at LAF_TableCustom_AddDelRow$2.actionPerformed(LAF_TableCustom_AddDelRow.java:45) 
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022) 

我如何做這些操作(removeRow,addRow),覆蓋各自的方法與我的自定義DefaultTableModel

answer,工作不

編輯

//Doesn't Work 
    @Override public void removeRow(int row) { 
    super.removeRow(row); 
    } 

    //Doesn't Work 
    @Override public void removeRow(int row) { 
    getDataVector().removeElementAt(row); 
    fireTableRowsDeleted(row, row); 
    } 

    //Doesn't Work (Not overriding the Method) 
    // @Override public void removeRow(int row) { 
    // getDataVector().removeElementAt(row); 
    // } 
+0

在打電話之前,'fireTableRowsDeleted',你實際上需要從底層數據結構中刪除行,以爲此,我建議使用某種類型的List,而不是數組,這非常簡單。如果你要在模型中擁有自己的數據結構,那麼你需要停止使用父類提供的功能 - 或者利用父類已經提供的支持 – MadProgrammer

+0

@MadProgrammer我編輯我的問題添加另一個嘗試... –

回答

1

從自己的代碼開始:

編輯PSRBTableModel類。

private Object[][] data; //Can't be final, you are changing!!! 

現在的方法:

@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 = 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]; 
     } 
    } 
    int maxCol = data[0].length < rowData.length?data[0].length:rowData.length; 
    for (int col = 0; col < maxCol; col++) { 
     newData[data.length][col] = rowData[col]; 
    } 
    data = newData; 
    } 

根據您的要求(檢查一些空對象以避免除外)適應你的代碼,我不知道你是如何使用!

現在, 如果從AbstractTableModel延長您PSRBTableModel類中刪除@Override標籤

class PSRBTableModel extends AbstractTableModel { 

但是,如果你的PSRBTableModel類是從DefaultTableModelclass延伸離開他們了!

class PSRBTableModel extends DefaultTableModel { 

在你LAF_TableCustom_AddDelRow類:

JButton bAddRow = new JButton("Add Row"); 
    bAddRow.addActionListener(new ActionListener() { 
     @Override public void actionPerformed(ActionEvent evt) { 
     ((PSRBTableModel)table.getModel()).addRow(
      new Object[] { new PanelSpinnerRadioButtonData(false, 10, 40) } 
     ); 
     table.updateUI(); 
     } 
    }); 

在你PanelSpinnerRadioButton

jbRemoveRow.addActionListener(new ActionListener() { 
     @Override public void actionPerformed(ActionEvent e) { 
     JTable table = (JTable)SwingUtilities.getAncestorOfClass(
      JTable.class, (Component) e.getSource()); 
     int row = table.getEditingRow(); 
     table.getCellEditor().stopCellEditing(); 
     ((PSRBTableModel)table.getModel()).removeRow(row); 
     // table.updateUI(); 
     } 
    }); 
2

的基本問題是,DefaultTableModel已由Vector,管理行/列的數據支持。但是你的擴展,實現了它自己的數據結構,使得冗餘是多餘的。

如果你花時間去看看在DefaultTabelModel的源代碼,你會發現,addRow(Object[])調用addRow(Vector)這使得使用getRowCount,其中要求你對它的實現......

/** 
* Adds a row to the end of the model. The new row will contain 
* <code>null</code> values unless <code>rowData</code> is specified. 
* Notification of the row being added will be generated. 
* 
* @param rowData   optional data of the row being added 
*/ 
public void addRow(Vector rowData) { 
    insertRow(getRowCount(), rowData); 
} 

/** 
* Adds a row to the end of the model. The new row will contain 
* <code>null</code> values unless <code>rowData</code> is specified. 
* Notification of the row being added will be generated. 
* 
* @param rowData   optional data of the row being added 
*/ 
public void addRow(Object[] rowData) { 
    addRow(convertToVector(rowData)); 
} 

這意味着, Vector沒有任何內容,但是你的代碼說有3行,這基本上觸發了所有的核心問題。

您可以選擇製作。使用DefaultTableModel並丟棄您自己的數據結構(datacolumns)或使用類似AbstractTableModel這將迫使您實現自己的數據結構。

5月的基本建議可能是第一次,因爲DefaultTableModel應該能夠提供您似乎需要的基本基本要求。

對於一個,真的,基本的例子:

class PSRBTableModel extends DefaultTableModel { 

    public PSRBTableModel(Object[][] data, Object[] columns) { 
     super(data, columns); 
    } 

    @Override 
    public Class getColumnClass(int columnIndex) { 
     if (getRowCount() > 0) { 
      Object value = getValueAt(0, columnIndex); 
      if (value instanceof PanelSpinnerRadioButton) { 
       return PanelSpinnerRadioButton.class; 
      } 
     } 
     return Object.class; 
    } 

    @Override 
    public boolean isCellEditable(int rowIndex, int columnIndex) { 
     return getColumnClass(columnIndex) == PanelSpinnerRadioButton.class; 
    } 
} 
+0

感謝您的時間,爲您的代碼'添加行'的作品,我需要評論我的'getValueAt','getColumnCount','getRowCount','setValueAt','getColumnName',但'Del Row' ,仍然不工作。 –

+0

回顧一下,不要讓我操縱Controls,Jspinner,JRadioButtons。 –

相關問題