JPanel无法在Mac上接收鼠标事件

时间:2019-07-10 03:15:11

标签: java swing

我在JFrame中有一个JPanel。我希望面板接收鼠标事件,但是当在macOS上运行时,它们转到JFrame。我尝试请求焦点,但没有帮助

SSCCE:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class PanelInFrame extends JPanel {

    public PanelInFrame() {
        this.setPreferredSize(new Dimension(100, 100));
        this.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                System.out.println("panel click!");
            }
        });
        this.setFocusable(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame();
            PanelInFrame panel = new PanelInFrame();
            frame.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseReleased(MouseEvent e) {
                    System.out.println("frame click!");
                }
            });
            frame.setContentPane(panel);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setResizable(false);
            frame.pack();
            frame.setVisible(true);
            panel.requestFocusInWindow();
        });
    }
}

我希望它报告“面板单击!”。 当我在Mac(macOs 10.14.5,Java 11.0.2)上运行此程序时,我只获得“框架单击”,而在Linux上我得到“面板单击”

在macOS上:

mac $ javac PanelInFrame.java 
mac $ java PanelInFrame
frame click!
frame click!
frame click!
mac $ java --version
java 11.0.2 2019-01-15 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.2+9-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.2+9-LTS, mixed mode)
mac $ uname -a
Darwin gavin-mpb.lan 18.6.0 Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 x86_64 i386 MacBookPro12,1 Darwin

在linux上:

linux $ javac PanelInFrame.java 
linux $ java PanelInFrame 
panel click!
panel click!
panel click!
linux $ java -version
java version "11.0.2" 2019-01-15 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.2+9-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.2+9-LTS, mixed mode)
linux $ uname -a
Linux hostname 4.15.0-50-generic #54-Ubuntu SMP Mon May 6 18:46:08 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

1 个答案:

答案 0 :(得分:1)

  

但是我似乎无法集中注意力,因此鼠标事件将转到框架中。

焦点仅与KeyEvent相关。

只有具有焦点的组件才能接收KeyEvent。

焦点对于MouseEvents无关紧要。当您单击某个组件时,Swing将在父/子层次结构中搜索第一个组件,以使用MouseListener查找该组件。

运行代码时,我会看到“面板单击”,表明MouseEvent确实要进入面板,而不是框架。

    this.setRequestFocusEnabled(true);
    this.requestFocusInWindow();
    this.requestFocus();
    this.grabFocus();

此外,请注意,您只能在可见的已实现组件上请求焦点,这基本上意味着您在框架上打包()或使用setVisible(true)之后请求焦点。

正确使用的方法是requestFocusInWindow()方法。

我不认为只需要setRequestFocusEnabled(true)就可以将setFocusable(true)放在面板上。

还要注意,所有Swing组件都应在Event Dispatch Thread (EDT)上创建。有关类的更好结构,请参见How to Make Frames的Swing教程中的Frame Demo示例,以确保代码在EDT上执行。

此外,pack()应该只是setVisible(...),这样setRisizable(...)之类的方法才能正常工作。