How to prevent mouse right-clicking on a JPopupMenu

50 Views Asked by At

I am trying to implement a GUI with Java. I bound a JPopupMenu to a JTable. The JPopupMenu becomes visible on mouse right-click on the JTable.

I managed to prevent mouse left-clicks on the JTable. I haven't been able to prevent mouse left-clicks on any item of the JPopupMenu. In fact each JMenuItem is bound to an ActionListener whose actionPerformed has no access to the mouse buttons. May I associate a MouseListener with a JMenuItem? If that is not possible then how can I make the JPopupMenu listen to mouse right-clicking only?

My goal is to reserve mouse left-clicks on the JTable for other tasks that are not related to the JPopupMenu. I suppose I will need to bind the JTable to another Listener. Can the same component (JTable) be associated with two different listeners?

Thank you in advance.

In the following I am pasting my code

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.border.EmptyBorder;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.border.EtchedBorder;
import java.awt.Color;
import java.awt.Font;
import java.awt.Dimension;
import java.awt.Point;
import javax.swing.UIManager;
import java.awt.Rectangle;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.JTextField;
import javax.swing.JTextArea;
import javax.swing.border.SoftBevelBorder;
import javax.swing.border.BevelBorder;
import javax.swing.JScrollPane;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.AbstractListModel;
import javax.swing.DefaultListModel;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Component;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;

import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

//--------- Define ActionListener
class PopupActionListener implements ActionListener 
{
    public void actionPerformed(ActionEvent actionEvent) {
     System.out.println("Selected: " + actionEvent.getActionCommand());
}
}


public class MyNewGUI extends JFrame 
{
    
// INSTANCE VARIABLE/COMPONENTS
        private JPanel ctpMain;
        private JTextField txtNewPoint;
        private JLabel lblNewPoint;
        private JButton btnNewPoint;
        private JButton btnDeleteAll;
        private JButton btnDeleteUnused;
        private JScrollPane scrPoints;
        private JButton btnExit;
        DefaultTableModel pointsTableModel = new DefaultTableModel ();
        JTable tblPoints = new JTable(pointsTableModel);
        JPopupMenu popupMenu = new JPopupMenu();
        JMenuItem menuItemAddBefore;
        JMenuItem menuItemAddAfter;
        JMenuItem menuItemRemove;
        JMenuItem menuItemRename;

/**************************** Launch the application *********************************************/
    public static void main(String[] args) 
    {
        try 
        {
            UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
        } catch (Throwable e) 
        {
            e.printStackTrace();
        }
        EventQueue.invokeLater(new Runnable()
        {
            public void run() 
            {
                try
                {
                    MyNewGUI frame = new MyNewGUI();
                    frame.setVisible(true);
                } catch (Exception e) 
                {
                    e.printStackTrace();
                }
            }
        });
    }

    
//**************************  JFrame Class Constructor --> Create the frame   ***************************                                                                                                                                                                                                                                                                                                                                                        */
    public MyNewGUI() 
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(new Rectangle(10, 10, 100, 100));
        setMinimumSize(new Dimension(100, 100));
        setFont(new Font("Arial", Font.BOLD, 16));
        setBounds(1050,200,800,800);
        setTitle("MyNewGUI");
        initComponents();
        
        btnExit = new JButton("Exit GUI");
        btnExit.setFont(new Font("Arial", Font.BOLD, 16));
        btnExit.setBounds(14, 254, 101, 26);
        ctpMain.add(btnExit);
        setVisible(true);
        createEvents();
    }
    
    /////////////////////////////////////////////////////////////////////////////////////////////////////////
    //  This method contains all of the code for creating and initializing components
    /////////////////////////////////////////////////////////////////////////////////////////////////////////
    private void initComponents()
    {
        setTitle("MyGUI");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 1041, 779);
        ctpMain = new JPanel();
        ctpMain.setBounds(new Rectangle(5, 5, 0, 0));
        ctpMain.setAlignmentY(5.0f);
        ctpMain.setAlignmentX(5.0f);
        ctpMain.setSize(new Dimension(10, 10));
        ctpMain.setPreferredSize(new Dimension(100, 100));
        ctpMain.setLocation(new Point(10, 10));
        ctpMain.setFont(new Font("Arial", Font.BOLD, 16));
        ctpMain.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
        setContentPane(ctpMain);
        
        btnNewPoint = new JButton("Add New Point");
        
        btnNewPoint.setBounds(14, 55, 167, 29);
        btnNewPoint.setFont(new Font("Arial", Font.BOLD, 16));
        
        txtNewPoint = new JTextField();
        txtNewPoint.setBounds(162, 14, 144, 29);
        txtNewPoint.setFont(new Font("Arial", Font.BOLD, 16));
        txtNewPoint.setColumns(10);
        
        lblNewPoint = new JLabel("  Point Identifier");
        lblNewPoint.setLocation(new Point(14, 19));
        lblNewPoint.setSize(new Dimension(136, 19));
        lblNewPoint.setDisplayedMnemonicIndex(1);
        lblNewPoint.setAutoscrolls(true);
        lblNewPoint.setFont(new Font("Arial", Font.BOLD, 16));
        
        JTextArea textArea = new JTextArea();
        textArea.setBounds(179, 197, 1, 16);
        textArea.setText("");
        
        JPanel pnPoints = new JPanel();
        pnPoints.setBounds(321, 21, 211, 668);
        pnPoints.setFont(new Font("Arial", Font.BOLD, 24));
        pnPoints.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null), "", TitledBorder.CENTER, TitledBorder.TOP, null, new Color(64, 0, 64)));
        ctpMain.setLayout(null);
        ctpMain.add(btnNewPoint);
        ctpMain.add(txtNewPoint);
        ctpMain.add(lblNewPoint);
        ctpMain.add(textArea);
        ctpMain.add(pnPoints);
        pnPoints.setLayout(null);
        
        scrPoints = new JScrollPane();
        scrPoints.setBounds(0, 0, 206, 668);
        pnPoints.add(scrPoints);
        
// --------- Initialize JTable Model with points fromCliff's code
        pointsTableModel.addColumn("Point Names");
        pointsTableModel.insertRow(0, new Object[] { "ONE" });
        pointsTableModel.insertRow(0, new Object[] { "TWO" });   
        pointsTableModel.insertRow(0, new Object[] { "THREE" });     
        scrPoints.setViewportView(tblPoints);
        tblPoints.setFocusable(true);
        tblPoints.setRowSelectionAllowed(true);
        tblPoints.setVisible(true);
        
        
// --------- Initialize popupMenu with items ---
        PopupListener myListener = new PopupListener();
        menuItemAddBefore = new JMenuItem("Add Point Before");
    //  menuItemAddBefore.addMouseListener(myListener);
        menuItemAddAfter = new JMenuItem("Add Point After");
    //  menuItemAddAfter.addMouseListener(myListener);
        menuItemRemove = new JMenuItem("Remove Current Point");
    //  menuItemRemove.addMouseListener(myListener);
        menuItemRename = new JMenuItem("Rename Current Point");
    //  menuItemRename.addMouseListener(myListener);
        popupMenu.add(menuItemAddBefore);
        popupMenu.add(menuItemAddAfter);
        popupMenu.add(menuItemRemove);
        popupMenu.add(menuItemRename);
        
// --------- Set popupMenu to tblPoints
        tblPoints.setComponentPopupMenu(popupMenu); 
        tblPoints.addMouseListener(myListener);
    //  tblPoints.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
                
        btnDeleteAll = new JButton("Delete All Points");
        btnDeleteAll.setFont(new Font("Arial", Font.BOLD, 16));
        btnDeleteAll.setBounds(14, 192, 167, 26);
        ctpMain.add(btnDeleteAll);
        
        btnDeleteUnused = new JButton("Delete Unused Points");
        btnDeleteUnused.setFont(new Font("Arial", Font.BOLD, 16));
        btnDeleteUnused.setBounds(14, 126, 205, 26);
        ctpMain.add(btnDeleteUnused);
    }
     
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//  This method contains all of the code for creating events
/////////////////////////////////////////////////////////////////////////////////////////////////////////
    private void createEvents() 
    {
        
//-------- Append Point To Point Names List ------------------------------------------------------------
        btnNewPoint.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent e) 
            {
                String newPoint = txtNewPoint.getText();    
                pointsTableModel.addRow(new Object[] {newPoint});
                txtNewPoint.setText("");
            }
        });
        
//-------- Remove Unused Points From Point Names List ---------------------------------------------------
        btnDeleteUnused.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent e)
            {
                // TO BE DEVELOPED
            }
        });

//-------- Empty Point Names List --------------------------------------------------------------------------        
        btnDeleteAll.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent e) 
            {
                while (pointsTableModel.getRowCount() > 0) 
                    pointsTableModel.removeRow(0);
            }
        });

//--------------- Button EXIT Handler --------------------------------------------------------------------------------------------------------------------
        btnExit.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent e) 
            {
                Object[] options = {"Exit Without Saving", "Exit With Saving","Cancel"};        //Custom button text
                int sel = JOptionPane.showOptionDialog(null ,
                    "Would you like to save your work before exiting ? ",
                    "EXIT WORK SESSION",
                    JOptionPane.YES_NO_CANCEL_OPTION,
                    JOptionPane.QUESTION_MESSAGE,
                    null,
                    options,
                    options[2]);
// Process Customer's Selection
                if (sel == 0) 
                {
                     JOptionPane.showMessageDialog(null, "You chose to exit your work session without saving!");
                     System.exit(0);    
                }
                if(sel == 1) 
                {
                     JOptionPane.showMessageDialog(null, "You chose to save your work session before exiting !");
//                   if(lstPoints != null && !pointsTableModel.isEmpty())  // If JList contains Points
//                   {
//                       pointsList.clear();     // Empty Points storage
//                       System.out.print("\n pointsList after clear():  " + pointsList);       // DEBUG-PURPOSE
//                       System.out.print("\n pointsTableModel :  " + pointsTableModel);         // DEBUG-PURPOSE
//                       System.out.print("\n pointsTableModel size:  " + pointsTableModel.size() );        // DEBUG-PURPOSE
//                       System.out.print("\n");
//                       for(int i=0; i < pointsTableModel.size(); i++)
//                           pointsList.add(pointsTableModel.get(i));    // Move Points from JList to Points storage
//                       System.out.print("Saved Points:  " + pointsList + "\n");
//                   }else 
//                       JOptionPane.showMessageDialog(null, "Your Ponts List is empty!"); 
//                   System.exit(0);    
                }
                if(sel == 2) 
                     JOptionPane.showMessageDialog(null, "You changed your mind !");
            }
        });
        
//--------------- JMenuItem Handler To Add Item Before Selected JTable Row-------------------------------------------------------------------------------------------------------
        menuItemAddBefore.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent ev) 
            {
                int row = tblPoints.getSelectedRow();
                  if (row == -1) 
                      return;
                System.out.print("Add Point to tblPoints Before Row:  " + row + "\n");
                String precedingPointName = JOptionPane.showInputDialog("Enter Following Point Name");
                System.out.println(precedingPointName);   
                pointsTableModel.insertRow(row, new Object[] {precedingPointName});
                tblPoints.getSelectionModel().clearSelection();
            }
        }); 
                
//--------------- JMenuItem Handler To Add Item After Selected JTable Row-------------------------------------------------------------------------------------------------------
        menuItemAddAfter.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent ev) 
            {
                int row = tblPoints.getSelectedRow();
                  if (row == -1 || !tblPoints.isCellEditable(row,0)) 
                      return;
                String value = tblPoints.getValueAt(row, 0).toString(); 
                System.out.print("Add Point to tblPoints After PointName: " + value + " On  Row:  " + row + "\n");
                String followingPointName = JOptionPane.showInputDialog("Enter Following Point Name");
                System.out.println(followingPointName);   
                pointsTableModel.insertRow(row +1, new Object[] {followingPointName});
                tblPoints.getSelectionModel().clearSelection();
            }
        });         
        
//--------------- JMenuItem Handler To Remove Selected JTable Row----------------------------------------------------------------------------------------------------------------
        menuItemRemove.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent ev) 
            {
                int row = tblPoints.getSelectedRow();
                  if (row == -1) 
                      return;
                System.out.print("Remove Point at tblPoints rown:  " + row + "\n");
                pointsTableModel.removeRow(tblPoints.getSelectedRow());
                tblPoints.getSelectionModel().clearSelection();
            }
        }); 
        
//--------------- JMenuItem Handler To Rename Item At Selected JTable Row----------------------------------------------------------------------------------------------------------------
        menuItemRename.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent ev) 
            {
                int row = tblPoints.getSelectedRow();
                 if (row == -1) 
                      return;
                 System.out.print("Rename Point at tblPoints rown:  " +  row + "\n");
                 String replacingPointName = JOptionPane.showInputDialog("Enter Current Point Replacing Name");
                 tblPoints.getModel().setValueAt(replacingPointName, row, 0);
                 tblPoints.getSelectionModel().clearSelection();
            }
        });         

    }  //-----------------------------------  End Of  createEvents() Method ----------------------------------------------------------------------  
    
// ********* Inner classes *********

    public class PopupListener extends MouseAdapter
    {
         public PopupListener()                 //  Default Constructor
         {
            System.out.print("\n Default PopupListener Constructor engaged \n ");
         }
         
         public void mousePressed(MouseEvent e) 
         
         {
            if(e.getButton() == MouseEvent.BUTTON3)
            {
                  Point p = e.getPoint();
                  Component c = e.getComponent();
                  int row = tblPoints.rowAtPoint(p);
                  System.out.print("\n `Selected row:  " + row + "\n");
                  if (row == -1)
                  {
                      tblPoints.getSelectionModel().clearSelection();
                      return;
                  }
                  else
                      tblPoints.setRowSelectionInterval(row, row);
            }
            else
                tblPoints.getSelectionModel().clearSelection();
         }
     }
}
1

There are 1 best solutions below

4
VGR On

It seems that you want right-clicking to select a table row if the row under the mouse pointer isn’t already selected, before showing the popup menu.

For that, you should remove tblPoints.setComponentPopupMenu(popupMenu); and instead display your JPopupMenu yourself, using your own MouseListener and key mappings. Normally, setComponentPopupMenu takes care of all of that, but you will need to customize that behavior.

MouseListener mousePopupListener = new MouseAdapter() {
    @Override
    public void mousePressed(MouseEvent event) {
        showPopup(event);
    }

    @Override
    public void mouseReleased(MouseEvent event) {
        showPopup(event);
    }

    @Override
    public void mouseClicked(MouseEvent event) {
        showPopup(event);
    }

    private void showPopup(MouseEvent event) {
        int row = tblPoints.rowAtPoint(event.getPoint());
        if (row >= 0 && !tblPoints.isRowSelected(row)) {
            tblPoints.setRowSelectionInterval(row, row);
        }

        if (popupMenu.isPopupTrigger(event)) {
            popupMenu.show(tblPoints, event.getX(), event.getY());
        }
    }
};
tblPoints.addMouseListener(mousePopupListener);

It is crucial to respond to mouse-down, mouse-up, and mouse-clicked events, because different platforms have different behaviors for popup menus.

However… this is not enough. Swing applications need to be accessible—meaning, among other things, they need to support using the keyboard to activate controls. (For instance, users can tab to a button and press space to ‘push’ it.) On most platforms, popup menus can be activated using the menu key on a PC keyboard (which usually has a ‘’ symbol on it), which Java represents as KeyEvent.VK_CONTEXT_MENU, as well as with Shift-F10.

String actionName = "showPopup";
Action keyboardMenuDisplayer = new AbstractAction(actionName) {
    private static final long serialVersionUID = 1;

    @Override
    public void actionPerformed(ActionEvent event) {
        Point location;

        PointerInfo info = MouseInfo.getPointerInfo();
        if (info != null) {
            location = info.getLocation();
            SwingUtilities.convertPointFromScreen(location, tblPoints);
        } else {
            int focusedRow =
                tblPoints.getSelectionModel().getLeadSelectionIndex();
            int focusedColumn =
                tblPoints.getColumnModel().getSelectionModel().getLeadSelectionIndex();
            if (focusedRow >= 0 && focusedColumn >= 0) {
                Rectangle cell =
                    tblPoints.getCellRect(focusedRow, focusedColumn, false);
                location = cell.getLocation();
            } else {
                location = new Point();
            }
        }
        
        popupMenu.show(tblPoints, location.x, location.y);
    }
};

tblPoints.getActionMap().put(actionName, keyboardMenuDisplayer);

InputMap inputMap = tblPoints.getInputMap(JComponent.WHEN_FOCUSED);
inputMap.put(KeyStroke.getKeyStroke("CONTEXT_MENU"), actionName);
inputMap.put(KeyStroke.getKeyStroke("shift F10"), actionName);