我在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
答案 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(...)之类的方法才能正常工作。