javaswingactionkeylistenerabstract-action

KeyListener inside an Action Class Not heard when using setAction()


I'd appreciate any advice to how I can get the following to work.

Originally all my actions were stuffed into the GUI. Then the GUI became quite large as the project progressed. So I've been moving all these actions into their own classes. In doing this some aspects loose their visibility. I have hopefully captured all the visibility issues, this I am sure of.

Now the issue.

Implementing the setAction() call on a JButton allows the action to work and it works well if it is only a MouseListener or MouseMotionListener. However, the KeyListener code is not reached. You'll note the //Debug Lines.

Below Code #1 - Code in the GUI class

    /**
 * This method initializes toolRotateButton
 * 
 * @return javax.swing.JButton
 */
private JToggleButton getToolRotateButton() {
    if (toolRotateButton == null) {
        toolRotateButton = new JToggleButton();
        toolRotateButton.setPreferredSize(dimension30x30);
        toolRotateButton.setHideActionText(true);
        toolRotateButton.setAction(new RotateAction(this));
        toolRotateButton.setToolTipText("Rotate Bearings or Selected Items");
    }
    return toolRotateButton;
}

Below Code #2 - Code in the RotateAction Class

package litetie.view.actions;

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.Collections;

import javafx.geometry.Point3D;

import javax.swing.AbstractAction;
import javax.swing.ImageIcon;

import litetie.LiteTieTRIAL;
import litetie.controller.Transform;
import litetie.listeners.UndoableRotateBearing;
import litetie.model.Coordinate;
import litetie.model.NegativeNumberException;
import litetie.model.UnitConvert;
import litetie.view.Zoom;

@SuppressWarnings("serial")
public class RotateAction extends AbstractAction {

    /**
     * The host provides all of the state of the interface
     */
    private final ActionHost host;

    /**
     * Constructs the move action, attaching it to the
     * given host GUI.
     * 
     * @param host The hosting GUI
     */
    public RotateAction(ActionHost host) {
        super("Rotate Selected Items", new ImageIcon(RotateAction.class.getResource("/icons_LiteTie_v2/rotate.png")));

        this.host = host;
    }

    @Override
    public void actionPerformed(ActionEvent e) {        
        host.setCurrentMouseMover(null); //set as nothing so that the new mouse listener can be applied later in the code
        host.setStrokeColourLabelText("Stroke");
        host.setStrokeColourWellBackground(host.getCurrentColour());
        host.setCurrentMouseClicker(firstClicker);
        host.setCurrentKeyEvent(currentKeyEvent);
    }
    /**
     * The easting of the first click
     */
    private double xClick;
    /**
     * The northing of the first click
     */
    private double yClick;
    /**
     * The elevation of the first click
     */
    private double zClick;

    /**
     * The offset between the click and the centre of the selection in easting
     */
    private double xOffset;
    /**
     * The offset between the click and the centre of the selection in northing
     */
    private double yOffset;

    /**
     * The offset between the click and the centre of the selection in elevation
     */
    private double zOffset;

    /**
     * Boolean flag that is set by the currentKeyEvent for when the "C" key is pressed down.
     */
    private boolean isVKCDown;
    /**
     * Boolean flag that is set by the currentKeyEvent for when the "P" key is pressed down.
     */
    private boolean isVKPDown;
    /**
     * Boolean flag that is set by the currentKeyEvent for when the "SHIFT" key is pressed down.
     */
    private boolean isVKShiftDown;

    /**
     * "currentKeyEvent" KeyListener to listen to when the various keys are pressed and then set the boolean flag
     * allowing the code in the mouse motion listener to run.
     */
    public KeyListener currentKeyEvent = new java.awt.event.KeyAdapter(){ 
        @Override
        public void keyPressed(KeyEvent e){
            if (e.getKeyCode() == KeyEvent.VK_C){
                LiteTieTRIAL.setConsoleOutput("Aim bearings at mouse location");
                System.out.println("Listening to key..."+e.getKeyChar()); //Debug currently this code is not reached.
                System.out.println("VKCDown");//Debug currently this code is not reached.
                isVKCDown = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_P){
                LiteTieTRIAL.setConsoleOutput("Rotate orientation of pattern");
                System.out.println("Listening to key..."+e.getKeyChar()); //Debug currently this code is not reached.
                System.out.println("VKPDown");//Debug currently this code is not reached.
                isVKPDown = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
                LiteTieTRIAL.setConsoleOutput("Rotation in increments of Five Degrees");
                System.out.println("Listening to key..."+e.getKeyChar()); //Debug currently this code is not reached.
                System.out.println("VKCShiftDown");//Debug currently this code is not reached.
                isVKShiftDown = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                host.setSelection(null);
            }
        }
        @Override
        public void keyReleased(KeyEvent e){
            if (e.getKeyCode() == KeyEvent.VK_C){
                isVKCDown = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_P){
                isVKPDown = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_SHIFT){
                isVKShiftDown = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                host.setSelection(null);
            }

        }
    };

    /**
     * "firstClicker" MouseListener to listen to when the mouse is clicked for the first time
     */
    private MouseListener firstClicker = new MouseAdapter() {
        //Mouse Event method
        public void mouseReleased(MouseEvent e) {
            //Get the Mouse Location and store it.
            Rectangle2D canvas = host.getCanvasSize();
            yClick = canvas.getY() + canvas.getHeight() - UnitConvert.pixelsToMeters(e.getY()) / Zoom.getScalingFactor();  //mouse's X location in the user co ords
            xClick = canvas.getX() + UnitConvert.pixelsToMeters(e.getX()) / Zoom.getScalingFactor(); //mouse's Y location in the user co ords
            zClick = 0;
            Rectangle2D bounds = new Rectangle2D.Double();
            host.getWorld().addAllCoordinates();

            Object selection = host.getSelection();
            if (selection == null) { // nothing selected yet
                selection = host.selectFirstObjectNear(xClick, yClick, zClick);
                if (selection == null) {
                    // nothing near the click location, wait for the next click
                    return;
                }
            }
            if (!(selection instanceof Collection<?>)) {
                // Put any single object into a collection so we only have one set of code
                host.setSelection(Collections.singleton(selection));
            }

            // Reaching this point means one or more items are selected
            // and are stored in a collection
            for (Coordinate c: host.getWorld().getCoordList().values()) {
                boolean isSelected = ((Collection<?>)selection).contains(c);
                //STEP THROUGH CHECK 
                if (isSelected) {
                    if (bounds.isEmpty()) {
                        bounds = c.getBounds();
                    } else {
                        bounds = bounds.createUnion(c.getBounds());
                    }
                }
            }
            host.setCentreBounds(bounds.getCenterX(), bounds.getCenterY(), 0);
            host.setDelta(0, 0, 0);

            yOffset = bounds.getCenterY() - yClick;
            xOffset = bounds.getCenterX() - xClick;

            host.setCurrentMouseClicker(nextClicker);
            host.setCurrentMouseMover(mover);
        }
    };

    /**
     * "nextClicker" MouseListener to listen to when the mouse is clicked for the second time
     */
    private MouseListener nextClicker = new MouseAdapter() {
        public void mouseReleased(MouseEvent e) {
            Rectangle2D canvas = host.getCanvasSize();
            double yMouseClick = canvas.getY() + canvas.getHeight() - UnitConvert.pixelsToMeters(e.getY()) / Zoom.getScalingFactor();
            double xMouseClick = canvas.getX() + UnitConvert.pixelsToMeters(e.getX()) / Zoom.getScalingFactor();

            try {
                if (!isVKShiftDown && !isVKPDown && !isVKCDown) {
                    Transform.rotateBearingsOfCollection((Collection<?>) host.getSelection(), xMouseClick, yMouseClick);
                    host.updateCanvas();
                } // ROTATE THE BEARING OF THE HOLE
                else if (isVKShiftDown && !isVKPDown && !isVKCDown) {
                    Transform.rotateBearingsOfCollectionByFive((Collection<?>) host.getSelection(), xMouseClick, yMouseClick);  
                    host.updateCanvas();
                } // ROTATE THE BEARING OF THE HOLE BY 5 DEGREE INCREMENTS  
                if (isVKPDown && !isVKShiftDown && !isVKCDown){
                    Transform.rotateCoordinateCollection((Collection<?>) host.getSelection(), xMouseClick, yMouseClick);
                    host.updateCanvas();
                }
                else if (isVKPDown && isVKShiftDown && !isVKCDown){
//                  Transform.rotatePointByFive((Collection<?>) host.getSelection(), xMouseClick, xMouseClick);
//                  host.updateCanvas();
                }

            } catch (NumberFormatException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (NegativeNumberException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

            host.updateCanvas();

            //UNDO RECORD
            host.addUndo(new UndoableRotateBearing(host.getWorld(), host.getSelection(), new Point3D(xClick + xOffset, yClick + yOffset, 0), new Point3D(xMouseClick, yMouseClick, 0)));
            System.out.println("Add Coordinate Move - UndoableMoveObject()");
            host.setSelection(null);
            host.updateCanvas();
            host.updateTrees();
            host.setCurrentMouseClicker(firstClicker);
            host.setCurrentMouseMover(host.getDefaultMouseMover());
            host.setCentreBounds(0, 0, 0);
            host.setDelta(0, 0, 0);
        }
    };

    /**
     * "mover" MouseMotionListener to listen to when the mouse is moved around the screen
     */
    private MouseMotionListener mover = new MouseMotionAdapter() {
        public void mouseMoved(MouseEvent e){
            Rectangle2D canvas = host.getCanvasSize();
            double yMouseClick = canvas.getY() + canvas.getHeight() - UnitConvert.pixelsToMeters(e.getY()) / Zoom.getScalingFactor();
            double xMouseClick = canvas.getX() + UnitConvert.pixelsToMeters(e.getX()) / Zoom.getScalingFactor();

            try {
                if (!isVKShiftDown && !isVKPDown && !isVKCDown) {
                    Transform.rotateBearingsOfCollection((Collection<?>) host.getSelection(), xMouseClick, yMouseClick);
                    host.updateCanvas();
                } // ROTATE THE BEARING OF THE HOLE
                if (isVKShiftDown && !isVKPDown && !isVKCDown) {
                    Transform.rotateBearingsOfCollectionByFive((Collection<?>) host.getSelection(), xMouseClick, yMouseClick);  
                    host.updateCanvas();
                } // ROTATE THE BEARING OF THE HOLE BY 5 DEGREE INCREMENTS  
                if (isVKPDown && !isVKShiftDown && !isVKCDown){
                    Transform.rotateCoordinateCollection((Collection<?>) host.getSelection(), xMouseClick, yMouseClick);
                    host.updateCanvas();
                }
                if (isVKPDown && isVKShiftDown && !isVKCDown){      
                }                   
            } catch (NumberFormatException e1) {
                System.out.println("rotated - Error");
            } catch (NegativeNumberException e1) {
                System.out.println("rotated - Error");
            }
            host.updateCanvas();
        }
    };

}

Of note: I have other actions working where I have left the KeyListener in the GUI and not brought it into the Action.

So why would the MouseListeners be functioning and the KeyListeners not functioning?


Solution

  • Granted that perhaps keybindings may be the more appropriate method it is not the method I've employed in this portion of the application.
    Thank you for your response however a friend suggested this today... which has fixed the KeyListener. Such a simple two lines.

    private JToggleButton getToolRotateButton() {
            if (toolRotateButton == null) {
                RotateAction action = new RotateAction(this); //Code Added to fix
    
                toolRotateButton = new JToggleButton();
                toolRotateButton.setPreferredSize(dimension30x30);
                toolRotateButton.setHideActionText(true);
                toolRotateButton.setAction(action);
                toolRotateButton.setToolTipText("Rotate Bearings or Selected Items");
                toolRotateButton.addKeyListener(action.currentKeyEvent); //Code Added to fix
            }
            return toolRotateButton;
        }
    

    For those who are interested.