繁体   English   中英

删除JTable的最后一行

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM