0

I need ur help, I want to add a Jbutton ( delete button) to each row of a Jtable. Till now, I added the button to each row, but I've a problem with the action. I tried this, but it's not working. When I click the button nothing happens. Can anyone help me please, i'm really stack. This is my code :

`public class Fenetre extends JFrame {

    Statement stmt;
    Map<Integer,Integer> row_table  = new HashMap<Integer,Integer>();
    JButton addUser;


  public Fenetre(){

    this.setLocationRelativeTo(null);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setTitle("JTable");
    this.setSize(600, 140);

    String requeteListeUser=" SELECT * FROM COMPTE_UTILISATEUR";
    try{
    stmt= (Statement) new Connexion().getConnection().createStatement();
    ResultSet resultat= stmt.executeQuery(requeteListeUser);
     resultat.last();
    String  title[] = {"Nom","Prenom","Matricule","Action"};
     int rowCount = resultat.getRow();

     Object[][] data  = new Object[rowCount][4];

     final JTable tableau = new JTable(data,title);
     JButton jButton2= new JButton("Supprimer");



    // this.tableau = new JTable(model);
    tableau.getColumn("Action").setCellRenderer(new ButtonRenderer());

    this.getContentPane().add(new JScrollPane(tableau), BorderLayout.CENTER); 
    int i=0;
        resultat.beforeFirst(); // on repositionne le curseur avant la première ligne 
        while(resultat.next()) //tant qu'on a quelque chose à lire
        {   
            //Remplire le tableau à deux dimensions Data[][] 
            for(int j=1;j<=4;j++)
            {
                 if(j != 4)data[i][j-1]=resultat.getObject(j)+"";
                 else { data[i][j-1] = jButton2;
                 jButton2.addActionListener(new java.awt.event.ActionListener() {
                  public void actionPerformed(java.awt.event.ActionEvent evt) {


                 ((DefaultTableModel)tableau.getModel()).removeRow(tableau.getSelectedRow());
                            }
                            });
                            }
                           }

            i++; 
            row_table.put(i, resultat.getInt("id_utilisateur"));

        }
 }
    catch(SQLException ex){
    System.out.println(ex);
    }

    addUser = new JButton("Ajouter un utilisateur");
    addUser.setPreferredSize(new Dimension(60,30));
    addUser.addActionListener(new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent arg0) {
            new AjouterUtilisateur().setVisible(true);
        }

    });

    this.getContentPane().add(addUser,BorderLayout.SOUTH);
  }

  //Classe modèle personnalisée
  class ZModel extends AbstractTableModel{
    private Object[][] data;
    private String[] title;

    //Constructeur
    public ZModel(Object[][] data, String[] title){
      this.data = data;
      this.title = title;
    }

    //Retourne le nombre de colonnes
    public int getColumnCount() {
      return this.title.length;
    }

    //Retourne le nombre de lignes
    public int getRowCount() {
      return this.data.length;
    }

    //Retourne la valeur à l'emplacement spécifié
    public Object getValueAt(int row, int col) {
      return this.data[row][col];
    }   
}

  public class ButtonRenderer extends JButton implements TableCellRenderer{

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean isFocus, int row, int col) {
      //On écrit dans le bouton ce que contient la cellule
      setText("Suuprimer");
      //On retourne notre bouton
      return this;

    }
  }
 public static void main(String[] args){
    //Fenetre fen = new Fenetre();
    new Menu().setVisible(true);
  }
}`
user3862042
  • 21
  • 1
  • 4
  • 8
  • 2
    Please post [MCVE](http://stackoverflow.com/help/mcve). Also see [Table Button Column](http://tips4java.wordpress.com/2009/07/12/table-button-column/) by @camickr – tenorsax Jul 31 '14 at 23:21
  • 1
    You need to define both cell renderer and cell editor. – tenorsax Jul 31 '14 at 23:30
  • Thanks for u answers Aqua. Can u please tell me how, i'm really stuck – user3862042 Jul 31 '14 at 23:36
  • See [How to add button in a row of JTable in Swing java?](http://stackoverflow.com/q/1475543/1048330) and [How to make a JButton in a JTable cell click-able?](http://stackoverflow.com/q/5555938/1048330). Also [Button Table Example](http://www.java2s.com/Code/Java/Swing-Components/ButtonTableExample.htm). I hope it helps. – tenorsax Jul 31 '14 at 23:41
  • Thanks for ur help, we've different methods :/ Can u please correct my code – user3862042 Jul 31 '14 at 23:49
  • Start by taking a look at [How to Use Tables](http://docs.oracle.com/javase/tutorial/uiswing/components/table.html), [Using Custom Renderers](http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#renderer) and [Using Other Editors](http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#editor) and when you understand all that, take a look at [Table Button Column](http://tips4java.wordpress.com/2009/07/12/table-button-column/). If you're still having issues, do search of SO, this question gets asked at least once a week... – MadProgrammer Jul 31 '14 at 23:56
  • *"Can u please correct my code"* - I'm sorry, but that's not how this works, we are not a debugging or coding service. We're happy to point you to resources you can use or examples that will help – MadProgrammer Jul 31 '14 at 23:57
  • Thank u guys for ur help, I will try this : Table Button Column by @camickr. – user3862042 Aug 01 '14 at 00:10
  • 1
    @user3862042 your current approach is incorrect. You should not store components in the model. The model is for data only. Renderers are used to render the data. You also need to add an implementation of an editor. The editor component allows you to make changes. The renderer is only painting cells. – tenorsax Aug 01 '14 at 00:12
  • 1
    -1 Question asked 10 days ago and the OP still hasn't posted a proper SSCCE: http://stackoverflow.com/questions/24873671/delete-button-in-a-jtable/24874106#comment39002764_24874106 – camickr Aug 01 '14 at 01:02

1 Answers1

12

Adding a button to a JTable's column to perform an action is...personally...restrictive and a little, well, 80's web...

Consider a different approach to the problem, instead of placing buttons in the columns, which take up screen real estate, which, if configured correctly could appear off screen and limit the user to a single, repetitive, action when dealing with multiple rows (ie, they want to delete multiple rows in one go), you could use a JToolBar and/or JMenu to provide access to the delete function, which would allow the user to select one or more rows and delete them in a single click...

Consider also, you provide a action which can be triggered by the Delete key on the keyboard to perform the same action, freeing the user from having to lift their hands from the keyboard...

You could even attach a JPopupMenu to the table as well...

This is, actually, a very common use case, and if designed properly, very re-usable...

For example...

Mutable table

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

public class EditRows {

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

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

                DefaultTableModel model = new DefaultTableModel();
                for (int index = 0; index < 13; index++) {
                    model.addColumn(Character.toString((char) (index + 65)));
                }
                for (int row = 0; row < 100; row++) {
                    Vector<String> rowData = new Vector<>(13);
                    for (int col = 0; col < 13; col++) {
                        rowData.add(row + "x" + col);
                    }
                    model.addRow(rowData);
                }

                JTable table = new JTable(model);
                DeleteRowFromTableAction deleteAction = new DeleteRowFromTableAction(table, model);

                JToolBar tb = new JToolBar();
                tb.add(deleteAction);

                InputMap im = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
                ActionMap am = table.getActionMap();
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "deleteRow");
                am.put("deleteRow", deleteAction);

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

    public abstract class AbstractTableAction<T extends JTable, M extends TableModel> extends AbstractAction {

        private T table;
        private M model;

        public AbstractTableAction(T table, M model) {
            this.table = table;
            this.model = model;
        }

        public T getTable() {
            return table;
        }

        public M getModel() {
            return model;
        }

    }

    public class DeleteRowFromTableAction extends AbstractTableAction<JTable, DefaultTableModel> {

        public DeleteRowFromTableAction(JTable table, DefaultTableModel model) {
            super(table, model);
            putValue(NAME, "Delete selected rows");
            putValue(SHORT_DESCRIPTION, "Delete selected rows");
            table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
                @Override
                public void valueChanged(ListSelectionEvent e) {
                    setEnabled(getTable().getSelectedRowCount() > 0);
                }
            });
            setEnabled(getTable().getSelectedRowCount() > 0);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("...");
            JTable table = getTable();
            if (table.getSelectedRowCount() > 0) {
                List<Vector> selectedRows = new ArrayList<>(25);
                DefaultTableModel model = getModel();
                Vector rowData = model.getDataVector();
                for (int row : table.getSelectedRows()) {
                    int modelRow = table.convertRowIndexToModel(row);
                    Vector rowValue = (Vector) rowData.get(modelRow);
                    selectedRows.add(rowValue);
                }

                for (Vector rowValue : selectedRows) {
                    int rowIndex = rowData.indexOf(rowValue);
                    model.removeRow(rowIndex);
                }
            }
        }

    }

}

Take a look at:

For more details.

If you're still determined to place a button in the table column, then take a look at Table Button Column

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • +1 awesome picture, worth so much more than words :) – tenorsax Aug 01 '14 at 00:54
  • @Aqua Yeah, if I had more time, I'd put a `JMenu` and `JPopupMenu` in there too, but I think I made my point ;) – MadProgrammer Aug 01 '14 at 00:56
  • Hope it gives you some more ideas – MadProgrammer Aug 01 '14 at 20:47
  • Does the delete action change the view index of the remaining table rows ? – Viraj Feb 16 '16 at 18:20
  • 1
    Since the view index is mapped to the model index, then yes – MadProgrammer Feb 16 '16 at 20:38
  • @MadProgrammer I am facing a problem where if 2 rows have the same data, the `indexOf` method picks up a row with lower index(not selected) and the duplicate row(selected) still has the older view index. – Viraj Feb 16 '16 at 20:42
  • 1
    @Viraj the problem is a difficult one, because, once you remove a row, you alter the view/model indices. You could walk backwards from the end of the table to the start, removing the rows by index directly instead – MadProgrammer Feb 16 '16 at 21:03
  • @MadProgrammer What I don't understand is, even if the lower index(not selected) is chosen and removed, why doesn't the view index of the remaining rows change ? For example: There are 5 rows which are identical. I select the bottom 4 and remove them(Note: Top 4 would be removed considering index 0 is returned in the indexOf method, which is fine with me). Now shouldn't the only remaining row have index 0 ? – Viraj Feb 16 '16 at 21:15
  • @Viraj Since I don't have your code I can't say, but in general yes – MadProgrammer Feb 16 '16 at 21:24
  • @MadProgrammer Its the `actionPerformed` method in `DeleteRowFromTableAction` class. – Viraj Feb 16 '16 at 21:28
  • @Viraj What about the table model? How is to managed? As you can see from the example, the basic idea works – MadProgrammer Feb 16 '16 at 21:28