簡體   English   中英

用jbutton從jtable中刪除一行

[英]remove a row from jtable with jbutton

我有一個帶有JButton這樣的JTable。 第一張照片

如果我單擊“ +”按鈕,則表格如下所示。 第二張照片

然后,如果我單擊第二行上的“-”按鈕,就可以了。

現在,該表只有一行,通過“ +”按鈕添加了。

所以問題是,我單擊行上的“-”按鈕,它在下面拋出異常:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1 >= 1
at java.util.Vector.elementAt(Vector.java:477)
at javax.swing.table.DefaultTableModel.setValueAt(DefaultTableModel.java:664)

發生了什么?

這是我的代碼:

public class TableDeleteButtonEditor extends AbstractCellEditor implements TableCellEditor{

/**
 * 
 */
private static final long serialVersionUID = 1L;
JButton button;
String label;
boolean isPushed;
Vector<Vector<String>> vPartsTypeData;

DefaultTableModel dtm;
JTable partsTypeValueTable;

public TableDeleteButtonEditor(Vector<Vector<String>> vPartsTypeData, DefaultTableModel dtm, JTable partsTypeValueTable) {

    // TODO Auto-generated constructor stub
    //this.setClickCountToStart(1);
    this.vPartsTypeData = vPartsTypeData;
    this.dtm = dtm;
    this.partsTypeValueTable = partsTypeValueTable;
    this.vPartsTypeData = vPartsTypeData;
    button = new JButton();
    int selectedRow = partsTypeValueTable.getSelectedRow();
    System.out.println("selectedRow:"+selectedRow);
    System.out.println("Count:"+vPartsTypeData.size());
    button.addActionListener(new deleteButtonListener());
}

public Component getTableCellEditorComponent(final JTable table, Object value,  boolean isSelected,int row, int column) {
    if (isSelected) {
        button.setFont(new Font("Arial",Font.PLAIN,30));
        button.setForeground(table.getSelectionForeground());  
        button.setBackground(table.getSelectionBackground());  
    } else {
        button.setFont(new Font("Arial",Font.PLAIN,30));
        button.setForeground(table.getForeground());  
        button.setBackground(table.getBackground());  
    }  
    label = (value == null) ? "" : value.toString();  
    button.setText(label);
    isPushed = true;  
    return button;  
}  

public Object getCellEditorValue() {  
    if (isPushed) {

    }  
    isPushed = false;  
    return new String(label);  
}  

public boolean stopCellEditing() {  
    isPushed = false;
    return super.stopCellEditing();  
}  

public class deleteButtonListener implements ActionListener
{
    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        System.out.println("-----");
        int selectedRow = partsTypeValueTable.getSelectedRow();
        //System.out.println("selectedRow:"+selectedRow);
        //System.out.println("Count:"+vPartsTypeData.size());
        dtm.removeRow(selectedRow-1);

        //vPartsTypeData.remove(partsTypeValueTable.getSelectedRow());
        System.out.println("tableCount:"+partsTypeValueTable.getRowCount());
        //dtm.fireTableChanged(null);
        partsTypeValueTable.setModel(dtm);
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                partsTypeValueTable.repaint();
                partsTypeValueTable.validate();
                partsTypeValueTable.updateUI();
                dtm.fireTableDataChanged();
            }
            });

    }
}

}

因此,稍微看一下堆棧跟蹤就可以使我們更好地了解正在發生的事情...

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1 >= 1
    at java.util.Vector.elementAt(Vector.java:477)
    at javax.swing.table.DefaultTableModel.setValueAt(DefaultTableModel.java:664)
    at javax.swing.JTable.setValueAt(JTable.java:2741)
    at javax.swing.JTable.editingStopped(JTable.java:4723)
    at javax.swing.AbstractCellEditor.fireEditingStopped(AbstractCellEditor.java:141)
    at javax.swing.AbstractCellEditor.stopCellEditing(AbstractCellEditor.java:85)

因此,基本上stopCellEditing會觸發對setValueAt的調用,傳入編輯rowcolumngetCellEditorValue的結果,但是由於這種情況在ActionListenerTableModel刪除該行之后發生,因此該行中斷了setValueAt是嘗試更新根本就不存在了(或者更糟的是完全不同的行)。

修改TableModel並不是TableCellEditor的責任,相反,它應該向TableModel報告一個狀態值,可以使用該狀態值來決定應該做什么。

編輯器的簡化版可能看起來像...

public class TableDeleteButtonEditor extends AbstractCellEditor implements TableCellEditor {

    /**
     *
     */
    private static final long serialVersionUID = 1L;
    JButton button;
    boolean isPushed;

    public TableDeleteButtonEditor() {
        button = new JButton();
        button.addActionListener(new DeleteButtonListener());
    }

    public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, int row, int column) {
        if (isSelected) {
            button.setFont(new Font("Arial", Font.PLAIN, 30));
            button.setForeground(table.getSelectionForeground());
            button.setBackground(table.getSelectionBackground());
        } else {
            button.setFont(new Font("Arial", Font.PLAIN, 30));
            button.setForeground(table.getForeground());
            button.setBackground(table.getBackground());
        }
        button.setText((value == null) ? "" : value.toString());
        isPushed = false;
        return button;
    }

    public Object getCellEditorValue() {
        return isPushed;
    }

    public class DeleteButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            isPushed = true;
            stopCellEditing();
        }
    }
}

編輯器的核心功能只是圍繞isPushed值的狀態。

現在,在調用setValueAt時, TableModel需要檢查該值並對其進行響應

@Override
public void setValueAt(Object aValue, int row, int column) {
    if (column == 0 && (aValue instanceof Boolean)) {
        boolean pushed = (boolean) aValue;
        if (pushed) {
            removeRow(row);
        }
    }
}                   

中提琴,行已刪除,每個人都很高興。

可運行的示例...

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                DefaultTableModel model = new DefaultTableModel(new String[]{"A"}, 0) {
                    @Override
                    public void setValueAt(Object aValue, int row, int column) {
                        if (column == 0 && (aValue instanceof Boolean)) {
                            boolean pushed = (boolean) aValue;
                            if (pushed) {
                                removeRow(row);
                            }
                        }
                    }
                };
                model.addRow(new Object[]{"-"});
                model.addRow(new Object[]{"-"});
                JTable table = new JTable(model);
                TableColumn column = table.getColumnModel().getColumn(0);
                column.setCellEditor(new TableDeleteButtonEditor());

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TableDeleteButtonEditor extends AbstractCellEditor implements TableCellEditor {

        /**
         *
         */
        private static final long serialVersionUID = 1L;
        JButton button;
        boolean isPushed;
        JTable partsTypeValueTable;

        public TableDeleteButtonEditor() {
            button = new JButton();
            button.addActionListener(new DeleteButtonListener());
        }

        public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, int row, int column) {
            partsTypeValueTable = table;
            if (isSelected) {
                button.setFont(new Font("Arial", Font.PLAIN, 30));
                button.setForeground(table.getSelectionForeground());
                button.setBackground(table.getSelectionBackground());
            } else {
                button.setFont(new Font("Arial", Font.PLAIN, 30));
                button.setForeground(table.getForeground());
                button.setBackground(table.getBackground());
            }
            button.setText((value == null) ? "" : value.toString());
            isPushed = false;
            return button;
        }

        public Object getCellEditorValue() {
            return isPushed;
        }

        public class DeleteButtonListener implements ActionListener {

            @Override
            public void actionPerformed(ActionEvent e) {
                isPushed = true;
                stopCellEditing();
            }
        }
    }
}

正如我所說的,我不喜歡這種方法,這是一個個人的事情,而是作為一個用戶,我發現它令人沮喪,更喜歡更多的東西,例如像這樣

但是,您可能還想看看“ 表格按鈕列”中的另一種方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM