[英]Removing last row of JTable
我有點新奇,希望你們能幫助我...
我是Java編程的初學者,我認為我對此感到頭疼。
除了讓我煩惱的一個小細節,我的程序運行得很好。 我有一個JTable,它在第一列上帶有一個按鈕,允許從表中刪除該行。 它工作正常,除了當我嘗試刪除表的最后一行時,按鈕停留在那里,然后表凍結,並且由於我收到“ Out of bound Exception”,我無法刪除任何行。 但是,當我使用命令table.getRowCount());時。
在刪除該行之前和之后,該表“知道”該行已刪除,但是正如我所說的,按鈕停留在那里。 縮略圖中的屏幕快照顯示了單擊“年份”單元格旁邊的按鈕之前和之后的情況。
最好添加一下,我要通過表格外部的按鈕在表格中添加行。
這是我的代碼:Main.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();
}
}
}
}
我對法語評論感到抱歉,它是我的母語。
似乎JTable在刪除最后一行后並未“刷新”自身。
我不在這里嗎?
非常感謝您,對於冗長的帖子感到抱歉,我試圖為您提供盡可能多的信息。
Djosimd編輯:
刪除第12行后,嘗試單擊第11行后的執行樁:
線程“ AWT-EventQueue-0”中的異常java.lang.ArrayIndexOutOfBoundsException:11> = 11,位於javax.swing.table.DefaultTableModel.setValueAt(未知源)的java.util.Vector.elementAt(未知源) javax.swing.JTable.editingStopped(未知源)處的java.swing.AbstractCellEditor.fireEditingStopped(javax.swing.DefaultCellEditor $ EditorDelegate.stopCellEditing(未知源)處的.JTable.setValueAt(未知源) javax.swing.plaf.basic.BasicTableUI $ Handler.mousePressed的.DefaultCellEditor.stopCellEditing(未知源)java.awt.Component.processMouseEvent的java.awt.AWTEventMulticaster.mousePressed(未知源)處的Unknown Source(未知源)在javax.swing.JComponent.processMouseEvent(未知源)在java.awt.Component.processEvent(未知源)在java.awt.Container.processEvent(在java.awt.Component.dispatchEventImpl(未知源)在.awt.Container.dispatchEventImpl(未知源)在java.awt.Com java.awt.LightweightDispatcher.remouseEvent(未知源)(java.awt.LightweightDispatcher.processMouseEvent(未知源)處java.awt.LightweightDispatcher.dispatchEvent(未知源)處java.awt.Container處的ponent.dispatchEvent(未知源)。 200美元的java.awt.Window.dispatchEventImpl(未知的來源)java.awt.EventQueue.dispatchEventImpl(未知的來源)的java.awt.EventQueue.access $ 200美元處的dispatchEventImpl(未知的來源) (未知源)在java.awt.EventQueue $ 3.run(未知源)在java.awt.EventQueue $ 3.run(在java.security.AccessController.doPrivileged(本機方法)在java.security.ProtectionDomain $ 1。 doIntersectionPrivilege(未知源)在java.security.ProtectionDomain $ 1.doIntersectionPrivilege(未知源)在java.awt.EventQueue $ 4.run(未知源)在java.awt.EventQueue $ 4.run(java.security.AccessController處) .doPrivileged(本地方法),位於java.security.ProtectionDomain $ 1.do java.awt.EventQueue.dispatchEvent上的IntersectionPrivilege(未知源)java.awt.EventDispatchThread.pumpOneEventForFilters(未知源)上java.awt.EventDispatchThread.pumpOneEventForFilters(未知源)處java.awt.EventDispatchThread.pumpEventsForFilter(未知源)處java.awt.EventDispatchThread.pumpEventsForHierarchy( java.awt.EventDispatchThread.pumpEvents(未知源)(java.awt.EventDispatchThread.pumpEvents(未知源)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();
}
}
}
}
正如camickr所提到的,您忘記刪除行時會忘記停止單元格版本,從而有可能繼續“編輯”單元格並觸發不再存在的行上的另一行刪除(因此索引超出范圍例外)
只需在最后取消按鈕的版本即可。 正如camickr所提到的,不需要fireTableDataChanged()
, removeRow()
會解決這一問題。
參見SSCCE(實際上並不那么短,但是我懶於修剪一些行)以進行演示:
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class TestJTable {
public class ButtonEditor extends DefaultCellEditor {
protected JButton button;
private final 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);
}
@Override
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;
}
@Override
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);
ButtonEditor.this.cancelCellEditing();
}
}
}
}
private static final String[] title = { "X", "Nom", "SRM", "Rend.", "%",
"Kg", };
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TestJTable().initUI();
}
});
}
protected void initUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultTableModel model = new DefaultTableModel(title, 4);
JTable table = new JTable(model);
table.getColumn("X").setCellEditor(new ButtonEditor(new JCheckBox()));
table.getColumn("X").setCellRenderer(new ButtonRenderer());
frame.add(new JScrollPane(table));
frame.pack();
frame.setVisible(true);
}
public static class ButtonRenderer extends JButton implements
TableCellRenderer {
private static final Color beige = new Color(218, 217, 158);
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean isFocus, int row,
int col) {
setBackground(beige);
// On écrit dans le bouton ce que contient la cellule
setText(value != null ? value.toString() : "");
// on retourne notre bouton
return this;
}
}
}
盡管這不能解決您的問題,但不要調用fireTableDataChanged,這是TableModel的工作。
問題出在TableEditor中。 我猜你不會停止單元格編輯。
簽出表格按鈕列 。 它為您實現了渲染器/編輯器。 您需要做的就是提供一個在單擊按鈕時要調用的動作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.