JFrame的getFocusOwner()没有帮助

时间:2012-07-02 21:02:41

标签: java swing

我正在使用Swing程序并遇到一些麻烦。该程序有两个窗口(都是JFrame)。主窗口很好,不应该与这个问题相关。

我遇到问题的窗口包含一个带有JPanel的JScrollPane,并且有一个JMenuBar。 JPanel上有一堆JTextComponents(一些JTextFields,一些JTextAreas)。

我想要做的是将一个连接到JMenuItem的ActionListener找到具有焦点的JTextComponent。

我在focused component referenceHow to find out which object currently has focus看过以前的帖子。我的问题是调用特定窗口的getFocusOwner()方法只返回JFrame的JRootPane,这完全没有用。有问题的JScrollPane和JPanel都可以根据他们的isFocusable()方法进行关注。即使我在单击菜单项之前实际在其中一个JTextComponents中输入文本,也会发生这种情况。当我打开菜单时,光标仍然在文本字段中闪烁。对于它的价值,getMostRecentFocusOwner()也只是返回JRootPane。

4 个答案:

答案 0 :(得分:2)

如果使用TextActions,则操作知道哪个JTextComponent具有焦点。我修改了一些我发现here的代码,以表明即使TextActions来自一个JTextArea,它们仍会自动处理任何有焦点的文本组件:

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

public class TextActionExample {
  public static void main(String[] args) {

    // Create a text area.
    JTextArea ta = new JTextArea(15, 30);
    ta.setLineWrap(true);

    // Add all actions to the menu (split into two menus to make it more
    // usable).
    Action[] actions = ta.getActions();
    JMenuBar menubar = new JMenuBar();
    JMenu actionmenu = new JMenu("Actions");
    menubar.add(actionmenu);

    JMenu firstHalf = new JMenu("1st Half");
    JMenu secondHalf = new JMenu("2nd Half");
    actionmenu.add(firstHalf);
    actionmenu.add(secondHalf);

    int mid = actions.length / 2;
    for (int i = 0; i < mid; i++) {
      firstHalf.add(actions[i]);
    }
    for (int i = mid; i < actions.length; i++) {
      secondHalf.add(actions[i]);
    }

    JTextField textField = new JTextField(20);
    JPanel textFieldPanel = new JPanel();
    textFieldPanel.add(textField);

    JPanel mainPanel = new JPanel(new GridLayout(1, 0, 5, 5));
    mainPanel.add(new JScrollPane(ta));
    mainPanel.add(new JScrollPane(new JTextArea(15, 30)));
    mainPanel.add(textFieldPanel);


    // Show it . . .
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.getContentPane().add(mainPanel);
    f.setJMenuBar(menubar);
    f.pack();
    f.setVisible(true);
  }
}

这是非常有趣的东西,我必须要了解更多。

答案 1 :(得分:1)

我想我已经解决了这个问题,因为当你点击一个菜单项时你失去了焦点,我们只需要等待焦点返回到组件,然后再检查谁有焦点,我使用了一个等待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]);
        }
    }
}

答案 2 :(得分:1)

我可能为时已晚,但我只是在我的JFrame构造函数中执行了以下操作。

this.rootPane.setFocusable(false);

现在

getFocusOwner()

将返回当前的JTextComponent而不是rootPane。 然后我在附加到我的JMenuItem的ActionListener中使用此代码来选择其中的文本。

if (getFocusOwner() instanceof JTextField)
{
    ((JTextField) getMostRecentFocusOwner()).selectAll();
}

应该注意的是,如果你有一个JScrollPane等,你可能必须对rootPane和textfields之间的所有组件使用setFocusable(false)。

希望这可以帮助其他人解决同样的问题!

来源:个人经历

答案 3 :(得分:0)

当我需要这个时,我写了一个焦点听众。我有一个带有两列JTextField的JPanel,焦点监听器跟踪用户上次使用的列。我允许用户通过单击按钮在最后一个聚焦列中输入一些文本。您只需将FocusListener的一个实例用于所有文本字段,并且具有引用最近聚焦的组件的字段。然后,您的菜单操作可以查询该字段以确定要使用的文本字段。

请参阅http://docs.oracle.com/javase/tutorial/uiswing/events/focuslistener.html