javaswingjpopupmenu

How to pass data from popup menu to actionlistener


I have a JPopUpMenu added to a JTables. I'm able to get the row of table over I've clicked, from popup management. When I click on menu item, how to pass the table row to the ActionListener of ItemMenu?

Mycode:

package it.rex.view;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;

import it.rex.model.Interventi;

public class InterventiView extends JFrame {

    private JPanel contentPane;
    private JTable table;
    private Interventi interventi;



    public InterventiView(Interventi i) {

        this.interventi = i;
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 500, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(28, 56, 422, 153);
        contentPane.add(scrollPane);

        table = new JTable();
        DefaultTableModel dtm = new DefaultTableModel(0, 0);

        // add header of the table
        String header[] = new String[] { "Id", "Descrizione", "Stato", "Data inizio", "Tipo", "Responsabile" };

        // add header in table model     
         dtm.setColumnIdentifiers(header);
         //set model into the table object
               table.setModel(dtm);

             // add row dynamically into the table  
             // for now only dummy data
        for (int count = 1; count <= 3; count++) {
                dtm.addRow(new Object[] { Integer.toString(count), "data", "data",
                        "data", "data", "data" });
         }

        table.getColumnModel().getColumn(2).setResizable(false);
        scrollPane.setViewportView(table);

        // prepare PopupMenu
        JPopupMenu popupMenu = new JPopupMenu();
        addPopup(table, popupMenu);

        JMenuItem mntmAggiungiIntervento = new JMenuItem("Aggiungi Intervento");
        popupMenu.add(mntmAggiungiIntervento);

        JMenuItem mntmModificaIntervento = new JMenuItem("Modifica Intervento");
        popupMenu.add(mntmModificaIntervento);

        JSeparator separator = new JSeparator();
        popupMenu.add(separator);

        JMenuItem mntmEliminaIntervento = new JMenuItem("Elimina Intervento");
        popupMenu.add(mntmEliminaIntervento);

        JButton btnOk = new JButton("Ok");
        btnOk.setBounds(262, 220, 89, 23);
        contentPane.add(btnOk);

        JButton btnAnnulla = new JButton("Annulla");
        btnAnnulla.setBounds(361, 220, 89, 23);
        contentPane.add(btnAnnulla);

        //Manage action over popupMenu
        mntmAggiungiIntervento.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                // Which row on JTable was selected?
                System.out.println("Add " + arg0.getActionCommand());
            }
        });

        mntmEliminaIntervento.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                // Which row on JTable was selected?
                System.out.println("Delete");

            }
        });

        mntmModificaIntervento.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                // Which row on JTable was selected?
                System.out.println("Modify");

            }
        });


    }

    // Mouse events
    private static void addPopup(Component component, final JPopupMenu popup) {
        component.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showMenu(e);
                }
            }
            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showMenu(e);
                }
            }
            private void showMenu(MouseEvent e) {
                popup.show(e.getComponent(), e.getX(), e.getY());

                // Identifico la riga
                JTable table = ((JTable) component);
                int tRaw = table.rowAtPoint(e.getPoint());

                if (tRaw >= 0 && tRaw < table.getRowCount()) {
                    table.setRowSelectionInterval(tRaw, tRaw);
                } else {
                    table.clearSelection();
                }

                System.out.println("Row: " + Integer.toString(tRaw+1));
            }
        });


    }

}

Solution

  • There are a number of ways you could do this, you could create a custom ActionListener which took a reference to the JTable, which is okay, it's a little messy and cumbersome to re-use, but it can work.

    Another solution would be to take advantage of the Action API, see How to Use Actions, which builts on the concept of the ActionListener and provides self contained properties make it much more re-usable - you can use in menus, buttons and keybindings, without needing to reimplement the functionality.

    I'd start by defining a "base" table action...

    public abstract class AbstractTableAction<TM extends TableModel> extends AbstractAction {
    
        private JTable table;
        private TM model;
    
        public AbstractTableAction(JTable table, TM model) {
            this.table = table;
            this.model = model;
        }
    
        public TM getModel() {
            return model;
        }
    
        public JTable getTable() {
            return table;
        }
    
        public int getSelectedRow() {
            return getTable().getSelectedRow();
        }
    
        public int getSelectedColumn() {
            return getTable().getSelectedColumn();
        }
    }
    

    Nothing special, it has a reference to a JTable and some helper methods.

    Now you just need to define the operations you want perform on the table...

    public class AddRowAction extends AbstractTableAction<DefaultTableModel> {
    
        public AddRowAction(JTable table, DefaultTableModel model) {
            super(table, model);
            putValue(NAME, "Add");
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Add @ " + getSelectedRow() + "x" + getSelectedColumn());
        }
    
    }
    
    public class DeleteRowAction extends AbstractTableAction<DefaultTableModel> {
    
        public DeleteRowAction(JTable table, DefaultTableModel model) {
            super(table, model);
            putValue(NAME, "Delete");
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Delete @ " + getSelectedRow() + "x" + getSelectedColumn());
        }
    
    }
    
    public class EditRowAction extends AbstractTableAction<DefaultTableModel> {
    
        public EditRowAction(JTable table, DefaultTableModel model) {
            super(table, model);
            putValue(NAME, "Edit");
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Edit @ " + getSelectedRow() + "x" + getSelectedColumn());
        }
    
    }
    

    Once you've got that all sorted, you just build the popup menu...

    JPopupMenu popupMenu = new JPopupMenu();
    popupMenu.add(new AddRowAction(table, dtm));
    popupMenu.add(new EditRowAction(table, dtm));
    popupMenu.add(new DeleteRowAction(table, dtm));
    

    Now, you need someway to show the popup menu, I prefer to use JComponent#setComponentPopupMenu, but this doesn't select the row/column of the table, which is sad :( so we need to it ourselves

    public class MousePopupHandler extends MouseAdapter {
    
        private JTable table;
        private JPopupMenu popupMenu;
    
        public MousePopupHandler(JTable table, JPopupMenu popupMenu) {
            this.table = table;
            this.popupMenu = popupMenu;
        }
    
        @Override
        public void mousePressed(MouseEvent e) {
            doPopup(e);
        }
    
        @Override
        public void mouseReleased(MouseEvent e) {
            doPopup(e);
        }
    
        @Override
        public void mouseClicked(MouseEvent e) {
            doPopup(e);
        }
    
        protected void doPopup(MouseEvent e) {
            if (e.isPopupTrigger()) {
                int x = e.getPoint().x;
                int y = e.getPoint().y;
                int row = table.rowAtPoint(e.getPoint());
                int col = table.columnAtPoint(e.getPoint());
                table.setRowSelectionInterval(row, row);
                table.setColumnSelectionInterval(col, col);
                popupMenu.show(table, x, y);
            }
        }
    
    }
    

    So, basically, this makes sure that the row/column that was clicked is selected before the popup menu is shown

    And that's about all you need, just wire it all together and you will know be able to make determinations about the context of the action when it's triggered

    import java.awt.EventQueue;
    import java.awt.event.ActionEvent;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import javax.swing.AbstractAction;
    import static javax.swing.Action.NAME;
    import javax.swing.JFrame;
    import javax.swing.JPopupMenu;
    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.TableModel;
    
    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 dtm = new DefaultTableModel(0, 0);
                    // add header of the table
                    String header[] = new String[]{"Id", "Descrizione", "Stato", "Data inizio", "Tipo", "Responsabile"};
                    // add header in table model     
                    dtm.setColumnIdentifiers(header);
                    //set model into the table object
    
                    // add row dynamically into the table  
                    // for now only dummy data
                    for (int count = 1; count <= 3; count++) {
                        dtm.addRow(new Object[]{Integer.toString(count), "data", "data",
                                                                        "data", "data", "data"});
                    }
    
                    JTable table = new JTable(dtm);
    
                    JPopupMenu popupMenu = new JPopupMenu();
                    popupMenu.add(new AddRowAction(table, dtm));
                    popupMenu.add(new EditRowAction(table, dtm));
                    popupMenu.add(new DeleteRowAction(table, dtm));
    
                    table.addMouseListener(new MousePopupHandler(table, popupMenu));
    
                    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 MousePopupHandler extends MouseAdapter {
    
            private JTable table;
            private JPopupMenu popupMenu;
    
            public MousePopupHandler(JTable table, JPopupMenu popupMenu) {
                this.table = table;
                this.popupMenu = popupMenu;
            }
    
            @Override
            public void mousePressed(MouseEvent e) {
                doPopup(e);
            }
    
            @Override
            public void mouseReleased(MouseEvent e) {
                doPopup(e);
            }
    
            @Override
            public void mouseClicked(MouseEvent e) {
                doPopup(e);
            }
    
            protected void doPopup(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    int x = e.getPoint().x;
                    int y = e.getPoint().y;
                    int row = table.rowAtPoint(e.getPoint());
                    int col = table.columnAtPoint(e.getPoint());
                    table.setRowSelectionInterval(row, row);
                    table.setColumnSelectionInterval(col, col);
                    popupMenu.show(table, x, y);
                }
            }
    
        }
    
        public abstract class AbstractTableAction<TM extends TableModel> extends AbstractAction {
    
            private JTable table;
            private TM model;
    
            public AbstractTableAction(JTable table, TM model) {
                this.table = table;
                this.model = model;
            }
    
            public TM getModel() {
                return model;
            }
    
            public JTable getTable() {
                return table;
            }
    
            public int getSelectedRow() {
                return getTable().getSelectedRow();
            }
    
            public int getSelectedColumn() {
                return getTable().getSelectedColumn();
            }
        }
    
        public class AddRowAction extends AbstractTableAction<DefaultTableModel> {
    
            public AddRowAction(JTable table, DefaultTableModel model) {
                super(table, model);
                putValue(NAME, "Add");
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Add @ " + getSelectedRow() + "x" + getSelectedColumn());
            }
    
        }
    
        public class DeleteRowAction extends AbstractTableAction<DefaultTableModel> {
    
            public DeleteRowAction(JTable table, DefaultTableModel model) {
                super(table, model);
                putValue(NAME, "Delete");
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Delete @ " + getSelectedRow() + "x" + getSelectedColumn());
            }
    
        }
    
        public class EditRowAction extends AbstractTableAction<DefaultTableModel> {
    
            public EditRowAction(JTable table, DefaultTableModel model) {
                super(table, model);
                putValue(NAME, "Edit");
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Edit @ " + getSelectedRow() + "x" + getSelectedColumn());
            }
    
        }
    }