如何将多个 MouseListeners 添加到单个 JFrame?

Posted

技术标签:

【中文标题】如何将多个 MouseListeners 添加到单个 JFrame?【英文标题】:How can I add multiple MouseListeners to a single JFrame? 【发布时间】:2017-04-08 04:24:41 【问题描述】:

我有两件事要做:在鼠标悬停时突出显示 JPanel 并在鼠标拖动时移动蓝色方块。问题是,这需要我将 MouseListeners 添加到不同的组件中。当我这样做时,我只能使用一个功能 - 另一个被阻止。我该怎么做才能使这两个功能都起作用?

注意: 有时 JFrame 不显示任何内容 - 您只需要继续运行它直到它显示(通常需要 2-3 次尝试)。如果它做了任何其他奇怪的事情,请继续运行它直到它工作。如果在 >5 次尝试后仍然无法正常工作,请发表评论。

应该是什么样子的:

Main(创建 JFrame、容器和子项,并添加 MouseListener)

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(创建将添加到子级的 MouseListener)

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(创建 MovableObject)

download blueSquare.png,或使用其他图像。记得把下面图片的名字改成你的名字。

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(创建用于 MovableObject 的 MouseListener)

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) 

【问题讨论】:

Sometimes the JFrame doesn't show anything - 在框架可见之前,所有组件都应该添加到框架中。 【参考方案1】:

没有详细查看您的代码,但我建议您需要将拖动 MouseListener 添加到可移动对象(即 JLabel)而不是面板。然后标签会得到拖动事件,面板会得到mouseEntered/Exited事件。

这将导致一个额外的问题,即当您在标签上移动时会生成 mouseExited 事件(您不希望发生这种情况)。查看:how to avoid mouseExited to fire while on any nested component 以获取此问题的解决方案。

【讨论】:

以上是关于如何将多个 MouseListeners 添加到单个 JFrame?的主要内容,如果未能解决你的问题,请参考以下文章

将 [(ngModel)] 添加到单选按钮组后,默认的 [checked] 不再起作用

如何将侦听器附加到单选按钮

如何将值从 DB 传递到单选按钮组?

通过RMAN将Oracle 11g R2 RAC数据迁移到单实例数据库

在NodeNS中,如何重定向到单页面应用程序中的特定页面?

单例--项目中用到单例的地方