0

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));
            }
        });


    }

}
Fabrizio R.
  • 117
  • 1
  • 14
  • 1
    Take a look at [How to Use Actions](http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html), basically I would create one or more actions which has a reference to the table and which knows what to do when triggered. I'd also consider having a look `JComponent#setComponentPopupMenu` which will allow it to take control and determine when to show the popup – MadProgrammer Feb 24 '17 at 23:19
  • 1
    Avoid using `null` layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify. You might like to have a look at [Why is it frowned upon to use a null layout in SWING?](http://stackoverflow.com/questions/6592468/why-is-it-frowned-upon-to-use-a-null-layout-in-swing) for more information – MadProgrammer Feb 24 '17 at 23:21
  • 1
    [As an example of using `Action` in a popup menu](http://stackoverflow.com/questions/22622973/jtable-copy-and-paste-using-clipboard-and-abstractaction/22623240#22623240) – MadProgrammer Feb 24 '17 at 23:27
  • 1
    [An extend example which demonstrates re-usability capabilities of `Action`](http://stackoverflow.com/questions/25070511/add-jbutton-to-each-row-of-a-jtable/25071138#25071138) – MadProgrammer Feb 24 '17 at 23:29
  • 1
    [Another example using `Action`, `JPopupMenu` and `JTable`](http://stackoverflow.com/questions/22583589/jtable-right-click-copy-paste-menu-to-copy-cell-data-on-one-click/22586925#22586925) – MadProgrammer Feb 24 '17 at 23:30

2 Answers2

0

Build a MyItemActionListener class implementing the ActionListener interface. Give the MyItemActionListener a private field myPopupManager. Pass the popup manager to the field upon construction of the Listener using an appropriate Constructor. Implement a method for the action triggered within your menu item as a method which takes the row number. Should look something like

 class MyItemActionListener implements ActionListener {
 private PopupManager myPopupManager;

 MyItemActionListener(PopupManager myPopupManager) {
    this.myPopupManager = myPopupManager;
 }

 @Override
 void actionPerformed(ActionEvent e) {
     ((MyMenuItem) e.getSource()).doSomething(myPopupManager.getRow());
 }

 }

Add the listener to your popup menu item. That should do the job.

Martin G
  • 229
  • 1
  • 6
0

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());
        }

    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366