【发布时间】:2014-02-16 21:26:47
【问题描述】:
我是新人,希望你们能帮助我...
我是 java 编程的初学者,我想我在这个方面超出了我的头脑。
我的程序运行良好,除了一个让我烦恼的小细节。我有一个 JTable,第一列上有一个按钮,允许从表中删除这一行。它运行良好,除非我尝试删除表格的最后一行,按钮停留在那里,然后表格冻结,我无法删除任何行,因为我收到“超出范围的异常”。但是,当我使用命令 table.getRowCount());
在删除线之前和之后,表格“知道”一条线已被删除,但正如我所说,按钮保留在那里。缩略图中的屏幕截图显示了单击“年份”单元格旁边的按钮之前和之后的情况。
补充一下,我正在通过表格外的按钮在表格中添加行。
这是我的代码: 主.java
static String [] title = {"X","Nom","SRM","Rend.","%","Kg",};
static Object[][] contenu;
static DefaultTableModel model1 = new DefaultTableModel(contenu, title);
static JTable tableauGrains = new JTable(model1);
tableauGrains.getColumn("X").setCellRenderer(new ButtonRenderer());
tableauGrains.getColumn("X").setCellEditor(new ButtonEditor(new JCheckBox()));
ButtonRenderer.java
import java.awt.Color;
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
public class ButtonRenderer extends JButton implements TableCellRenderer{
public Component getTableCellRendererComponent( JTable table, Object value,
boolean isSelected, boolean isFocus,
int row, int col) {
Color beige = new Color(218, 217, 158);
setBackground(beige);
//On écrit dans le bouton ce que contient la cellule
setText((value != null) ? value.toString() : "");
//on retourne notre bouton
return this;
}
}
ButtonEditor.java
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.swing.DefaultCellEditor;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class ButtonEditor extends DefaultCellEditor {
protected JButton button;
private DeleteButtonListener bListener = new DeleteButtonListener();
/**
* Constructeur avec une checkBox
* @param checkBox
* @param count
*/
@SuppressWarnings("deprecation")
public ButtonEditor(JCheckBox checkBox) {
//Par défaut, ce type d'objet travaille avec un JCheckBox
super(checkBox);
//On crée à nouveau notre bouton
button = new JButton();
button.setOpaque(true);
//On lui attribue un listener
button.addActionListener(bListener);
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
//On précise le numéro de ligne à notre listener
bListener.setRow(row);
//Idem pour le numéro de colonne
//On passe aussi le tableau en paramètre pour des actions potentielles
bListener.setTable(table);
//On réaffecte le libelle au bouton
button.setText( (value == null) ? "" : value.toString() );
//On renvoie le bouton
return button;
}
class DeleteButtonListener implements ActionListener {
private int row;
private JTable table;
public void setRow(int row){this.row = row;}
public void setTable(JTable table){this.table = table;}
public void actionPerformed(ActionEvent event) {
if(table.getRowCount() > 0){
//On affiche un message
System.out.println("coucou du bouton: "+ ((JButton)event.getSource()).getText() );
((DefaultTableModel)table.getModel()).removeRow(this.row);
((DefaultTableModel)table.getModel()).fireTableDataChanged();
}
}
}
}
对于法语 cmets,我很抱歉,这是我的母语。
在删除最后一行之后,JTable 似乎没有“刷新”自身。
我在这里不合群吗?
非常感谢你,很抱歉这篇长文,我试图给你尽可能多的信息。
乔西姆德 编辑:
删除后尝试点击第11行后的执行桩 第 12 行:
线程“AWT-EventQueue-0”中的异常 java.lang.ArrayIndexOutOfBoundsException: 11 >= 11 在 java.util.Vector.elementAt(未知来源)在 javax.swing.table.DefaultTableModel.setValueAt(未知来源)在 javax.swing.JTable.setValueAt(未知来源)在 javax.swing.JTable.editingStopped(未知来源)在 javax.swing.AbstractCellEditor.fireEditingStopped(未知来源)在 javax.swing.DefaultCellEditor$EditorDelegate.stopCellEditing(未知 来源)在 javax.swing.DefaultCellEditor.stopCellEditing(未知 来源)在 javax.swing.plaf.basic.BasicTableUI$Handler.mousePressed(未知 来源)在 java.awt.AWTEventMulticaster.mousePressed(未知来源) 在 java.awt.Component.processMouseEvent(Unknown Source) 在 javax.swing.JComponent.processMouseEvent(未知来源)在 java.awt.Component.processEvent(未知来源)在 java.awt.Container.processEvent(未知来源)在 java.awt.Component.dispatchEventImpl(未知来源)在 java.awt.Container.dispatchEventImpl(未知来源)在 java.awt.Component.dispatchEvent(未知来源)在 java.awt.LightweightDispatcher.retargetMouseEvent(未知来源)在 java.awt.LightweightDispatcher.processMouseEvent(未知来源)在 java.awt.LightweightDispatcher.dispatchEvent(未知来源)在 java.awt.Container.dispatchEventImpl(未知来源)在 java.awt.Window.dispatchEventImpl(未知来源)在 java.awt.Component.dispatchEvent(未知来源)在 java.awt.EventQueue.dispatchEventImpl(未知来源)在 java.awt.EventQueue.access$200(未知来源)在 java.awt.EventQueue$3.run(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) 在 java.security.ProtectionDomain$1.doIntersectionPrivilege(未知 来源)在 java.security.ProtectionDomain$1.doIntersectionPrivilege(未知 源)在 java.awt.EventQueue$4.run(未知源)在 java.awt.EventQueue$4.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) 在 java.security.ProtectionDomain$1.doIntersectionPrivilege(未知 源)在 java.awt.EventQueue.dispatchEvent(未知源)在 java.awt.EventDispatchThread.pumpOneEventForFilters(未知来源) 在 java.awt.EventDispatchThread.pumpEventsForFilter(未知来源) 在 java.awt.EventDispatchThread.pumpEventsForHierarchy(未知 来源)在 java.awt.EventDispatchThread.pumpEvents(未知来源) 在 java.awt.EventDispatchThread.pumpEvents(Unknown Source) 在 java.awt.EventDispatchThread.run(未知来源)
SSCCE:
import java.awt.*;
import java.awt.event.*;
import javax.swing.table.*;
import javax.swing.*;
public class FooGui {
static String[] title = { "X", "Nom", "SRM", "Rend.", "%", "Kg"};
static Object[][] contenu;
// !! static DefaultTableModel model1 = new DefaultTableModel(contenu, title);
static DefaultTableModel model1 = new DefaultTableModel(title, 0);
static JTable tableauGrains = new JTable(model1);
public static void main(String[] args) {
tableauGrains.getColumn("X").setCellRenderer(new ButtonRenderer());
tableauGrains.getColumn("X").setCellEditor(new ButtonEditor(new JCheckBox()));
for (int i = 0; i < 10; i++) {
String btnText = "Btn " + (i + 1);
Object[] rowData = {btnText, "", "", "", "", ""};
model1.addRow(rowData);
}
JOptionPane.showMessageDialog(null, new JScrollPane(tableauGrains));
}
}
class ButtonRenderer extends JButton implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean isFocus, int row, int col) {
Color beige = new Color(218, 217, 158);
setBackground(beige);
setText((value != null) ? value.toString() : "");
return this;
}
}
class ButtonEditor extends DefaultCellEditor {
protected JButton button;
private DeleteButtonListener bListener = new DeleteButtonListener();
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton();
button.setOpaque(true);
button.addActionListener(bListener);
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
System.out.printf("row is: %d%n", row);
bListener.setRow(row);
bListener.setTable(table);
// On réaffecte le libelle au bouton
button.setText((value == null) ? "" : value.toString());
// On renvoie le bouton
return button;
}
class DeleteButtonListener implements ActionListener {
private int row;
private JTable table;
public void setRow(int row) {
this.row = row;
}
public void setTable(JTable table) {
this.table = table;
}
public void actionPerformed(ActionEvent event) {
if (table.getRowCount() > 0) {
System.out.println("coucou du bouton: " + ((JButton) event.getSource()).getText());
((DefaultTableModel) table.getModel()).removeRow(this.row);
stopCellEditing(); // !! not sure if this will help or not.
//!! ((DefaultTableModel) table.getModel()).fireTableDataChanged();
}
}
}
}
【问题讨论】:
-
您也应该发布异常堆栈跟踪。这看起来好像外部代码(调用您的 ButtonListener)仍然引用您删除的最后一行,因此,在从 ButtonListener 返回后,仍然想要访问最后一行的调用者会收到错误。但是需要堆栈跟踪来找出究竟是什么触发了异常。