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