简体   繁体   中英

How can I add multiple MouseListeners to a single JFrame?

I have two things that I am trying to do: highlight a JPanel on mouse hover and move a blue square on mouse drag. The thing is, this requires me to add MouseListeners to different components. When I do this, I can only use one feature - the other is blocked. What can I do so that both features work?

NOTE: Sometimes the JFrame doesn't show anything - you just have to keep running it until it does (usually takes 2-3 tries). If it does any other weird stuff just keep running it until it works. Comment if it still isn't working right after >5 tries.

What it should look like: 成功的开始截图

Main (creates the JFrame, the container, and the children, and adds the MouseListeners)

public class Main extends JFrame{
    private static final long serialVersionUID = 7163215339973706671L;
    private static final Dimension containerSize = new Dimension(640, 477);
    static JLayeredPane layeredPane;
    static JPanel container;

    public Main() {
        super("Multiple MouseListeners Test");
        setSize(640, 477);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setVisible(true);

        layeredPane = new JLayeredPane();
        layeredPane.setPreferredSize(containerSize);
        getContentPane().add(layeredPane);

        createContainer();

        layeredPane.add(container, JLayeredPane.DEFAULT_LAYER);

        createChildren(4, 4);

        new MovableObject();

        MovableObjectMouseListener moml = new MovableObjectMouseListener();
        //comment these two out and the highlighter works
        layeredPane.addMouseListener(moml);
        layeredPane.addMouseMotionListener(moml);
    }

    private void createChildren(int columns, int rows){
        for (int i = 0; i < columns; i++){
            for (int j = 0; j < rows; j++){
                JPanel child = new JPanel(new BorderLayout());
                child.setBackground(Color.LIGHT_GRAY);
                //comment this out and you can move the MovableObject
                child.addMouseListener(new HighlightJPanelsMouseListener());
                container.add(child);
            }
        }
    }

    private JPanel createContainer(){
        container = new JPanel();
        container.setLayout(createLayout(4, 4, 1, 1));
        container.setPreferredSize(containerSize);
        container.setBounds(0, 0, containerSize.width, containerSize.height);
        return container;
    }

    private GridLayout createLayout(int rows, int columns, int hGap, int vGap){
        GridLayout layout = new GridLayout(rows, columns);
        layout.setHgap(hGap);
        layout.setVgap(vGap);
        return layout;
    }

    public static void main(String[] args) {
        new Main();
    }
}

HighlightJPanelsMouseListener (creates the MouseListeners that will be added to the children)

public class HighlightJPanelsMouseListener implements MouseListener{
    private Border grayBorder = BorderFactory.createLineBorder(Color.DARK_GRAY);

    public HighlightJPanelsMouseListener() {
    }

    public void mouseEntered(MouseEvent e) {
        Component comp = (Component) e.getSource();
        JPanel parent = (JPanel) comp;
        parent.setBorder(grayBorder);
        parent.revalidate();
    }

    public void mouseExited(MouseEvent e) {
        Component comp = (Component) e.getSource();
        JPanel parent = (JPanel) comp;
        parent.setBorder(null);
        parent.revalidate();
    }

    public void mousePressed(MouseEvent e){}
    public void mouseReleased(MouseEvent e){}
    public void mouseClicked(MouseEvent e) {}
}

MovableObject (creates the MovableObject)

download blueSquare.png , or use another image. Remember to change the name of the image below to whatever yours is.

public class MovableObject {
    public MovableObject() {
        JPanel parent = (JPanel) Main.container.findComponentAt(10, 10);
        ImageIcon icon = null;
        //use any image you might have laying around your workspace - or download the one above
        URL imgURL = MovableObject.class.getResource("/blueSquare.png");

        if (imgURL != null){
            icon = new ImageIcon(imgURL);
        }else{
            System.err.println("Couldn't find file");
        }

        JLabel movableObject = new JLabel(icon);
        parent.add(movableObject);
        parent.revalidate();
    }
}

MovableObjectMouseListener (creates the MouseListener to be used for MovableObject)

public class MovableObjectMouseListener implements MouseListener, MouseMotionListener{
    private JLabel replacement;
    private int xAdjustment, yAdjustment;

    public void mousePressed(MouseEvent e){
        replacement = null;
        Component c =  Main.container.findComponentAt(e.getX(), e.getY());

        if (!(c instanceof JLabel)){
            return;
        }

        Point parentLocation = c.getParent().getLocation();
        xAdjustment = parentLocation.x - e.getX();
        yAdjustment = parentLocation.y - e.getY();
        replacement = (JLabel)c;
        replacement.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);

        Main.layeredPane.add(replacement, JLayeredPane.DRAG_LAYER);
        Main.layeredPane.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    }

    public void mouseDragged(MouseEvent me){
        if (replacement == null){
            return;
        }

        int x = me.getX() + xAdjustment;
        int xMax = Main.layeredPane.getWidth() - replacement.getWidth();
        x = Math.min(x, xMax);
        x = Math.max(x, 0);

        int y = me.getY() + yAdjustment;
        int yMax = Main.layeredPane.getHeight() - replacement.getHeight();
        y = Math.min(y, yMax);
        y = Math.max(y, 0);

        replacement.setLocation(x, y);
     }


    public void mouseReleased(MouseEvent e){
        Main.layeredPane.setCursor(null);

        if (replacement == null){
            return;
        }

        int xMax = Main.layeredPane.getWidth() - replacement.getWidth();
        int x = Math.min(e.getX(), xMax);
        x = Math.max(x, 0);

        int yMax = Main.layeredPane.getHeight() - replacement.getHeight();
        int y = Math.min(e.getY(), yMax);
        y = Math.max(y, 0);


        Component c = Main.container.findComponentAt(x, y);
        Container parent = (Container) c;
        parent.add(replacement);
        parent.validate();  
    }

    public void mouseClicked(MouseEvent e) {}
    public void mouseMoved(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

Didn't look at your code in detail but I would suggest that you need to add the drag MouseListener to the movable object (ie. the JLabel) and not the panel. Then the label will get the drag events and the panel will get the mouseEntered/Exited events.

This will lead to an additional problem with the mouseExited event now being generated when you move over the label (which you don't want to happen). Check out: how to avoid mouseExited to fire while on any nested component for a solution to this problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM