我正在使用 Swing 程序,但遇到了一些麻烦。该程序有两个窗口(都是 JFrames)。主窗口很好,应该与此问题无关。
我遇到问题的窗口包含一个带有 JPanel 的 JScrollPane,并且有一个 JMenuBar。JPanel 上有一堆 JTextComponents(一些 JTextFields,一些 JTextAreas)。
我想要做的是将 ActionListener 附加到 JMenuItem 找到具有焦点的 JTextComponent。
我在focused component reference和How to find out which object current has focus 上看过之前的帖子。我的问题是调用特定窗口的getFocusOwner()方法只会返回 JFrame 的JRootPane,这完全没有帮助。有问题的 JScrollPane 和 JPanel 都可以根据它们的isFocusable()方法聚焦。即使我在单击菜单项之前实际将文本输入到 JTextComponent 之一中,也会发生这种情况。当我打开菜单和所有内容时,光标仍然在文本字段中闪烁。对于它的价值,getMostRecentFocusOwner()也简单地返回 JRootPane。
我想我已经解决了这个问题,因为当您单击菜单项时您会失去焦点,我们只需等待焦点返回到组件,然后再检查谁拥有焦点,我已经使用摆动计时器完成了此操作等待 100 毫秒,然后执行其方法来检查哪个组件获得焦点:
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.TimerTask;
import javax.swing.*;
public class JavaApplication180 extends JFrame {
private JTextField[] JTextFields;
private JMenuBar menuBar;
private JMenu menu;
private JMenuItem item;
public JavaApplication180() {
initComponents();
createAndShowUI();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new JavaApplication180();
}
});
}
private void createAndShowUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new GridLayout(2, 2, 10, 10));
setJMenuBar(menuBar);
addComponentsToPane();
pack();
setVisible(true);
}
private void initComponents() {
JTextFields = new JTextField[4];
menuBar = new JMenuBar();
item = new JMenuItem("Who has focus?");
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
TimerTask tt = new TimerTask() {
@Override
public void run() {
JOptionPane.showMessageDialog(null, getMostRecentFocusOwner().getName());
}
};
new java.util.Timer().schedule(tt, 100);
}
});
menu = new JMenu("File");
menu.add(item);
menuBar.add(menu);
}
private void addComponentsToPane() {
for (int i = 0; i < JTextFields.length; i++) {
JTextFields[i] = new JTextField();
JTextFields[i].setText(String.valueOf(i));
JTextFields[i].setName(String.valueOf(i));
getContentPane().add(JTextFields[i]);
}
}
}
Run Code Online (Sandbox Code Playgroud)